; Chocks Away: Extra Missions
; Written by Andrew Hutchings
; (C) 1991 The Fourth Dimension
; Reverse-engineered by Christopher Bazley (cs99cjb@gmail.com)
; Version 1, 14th October 2018

; I chose to reverse-engineer 'Extra Missions' instead of the original game
; because it has more features and therefore this is presumably a superset of
; the original game's code.
; This is a work in progress: some labels and names may be a result of wrong
; inferences/guesses. It would be possible to make the code more maintainable,
; e.g. by use of literal pools, but that would make it impossible to compare
; the assembled code directly with the original for validation. For the same
; reason, suspect code (including dead and redundant code) has been annotated
; with 'bug' comments instead of fixing or deleting it.

; Generated by Armalyser 0.62 (16-Oct-2007)
; Assemble with ObjAsm -ABSolute and link with Link -bin

; Operating system
OS_ReadVduVariables EQU &000031
OS_Byte             EQU &000006
OS_WriteC           EQU &000000
Sound_AttachVoice   EQU &040185
Sound_Control       EQU &040189
Sound_Volume        EQU &040180
Sound_Speaker       EQU &040143
OS_Write0           EQU &000002
OS_Mouse            EQU &00001C
OS_Word             EQU &000007
XJoy_Read0          EQU &0CFFC0
XJoy_Read1          EQU &0CFFC1

ReadKey EQU &81
ScanKeyboard EQU &FF
KeyIsPressed EQU &FF
GetChar EQU &91
SpecifyInputStream EQU 2
FlushBuffer EQU &15
SetMousePos EQU &15
InputStreamSerialPort EQU 1
InputStreamKeyboard EQU 0
WriteIntervalTimer EQU 4
SpecifyOutputStream EQU 3
OutputStreamEnableSerialPort EQU 1
OutputStreamDisableVDU EQU 2
SetDisplayBuffer EQU &71
SetDrawBuffer EQU &70
SplitCursors EQU 4
JoinCursors EQU 5
SetCursorPos EQU &1F
ReadIntervalTimer EQU 3
ReadSystemClock EQU 1
WriteSystemClock EQU 2
VDUVarDisplayStart EQU &95
VDUVarEndOfList EQU -1
PixelCopyChunk EQU 40
PixelFillChunk EQU 56

; Map of memory referenced by the code but not declared within this file
MemRandom               EQU &000223D8
MemAircraftDataArray    EQU &00023194
MemTargetDataArray      EQU &00023FF4
MemHitList              EQU &000278D4
MemPlayerBulletsArray   EQU &0002794C
MemExplosionOut         EQU &0002B2D8
MemSmoke                EQU &0002C4E4
MemExplosionIn          EQU &0002C6F0
MemCollisionBoxes       EQU &0002C76C
MemAircraftPointerArray EQU &0002DE5C
MemTargetPointerArray   EQU &0002DF38
MemSrcCoords            EQU &0002E008
MemLineCoords           EQU &0002E800
MemSpanPointerArray     EQU &0002EFE8
MemSpanStartEnd         EQU &0002FBB8
MemCosine               EQU &00030B94
MemSine                 EQU &0003463C
MemObjArray             EQU &00037920
MemObj3DAddrArray       EQU &0003DADC
GroundCol               EQU &0004A6C0
MemGraphics             EQU &00057380

BytesPerAddressLog2 EQU 2
BytesPerAddress EQU (1:SHL:BytesPerAddressLog2)
BytesPerQuotientLog2 EQU 2

; Land file format =====================

; Mesh data header
MeshSimplifyDist EQU 0
MeshPrimCountMinus1 EQU 4
MeshVertCountMinus1 EQU 8
MeshSimplePrimCountMinus1 EQU 12
MeshSimpleVertCountMinus1 EQU 16
; 20
MeshClipDist EQU 24
MeshPolygonStyle EQU 28
BytesPerMeshHdr EQU 32

; MeshPrimCountMinus1 values
MeshPrimCountMinus1DrawPoint EQU &FF

; MeshPolygonStyle values
PolygonStyleNoOutline EQU 0
PolygonStyleBlackOutline EQU 1
PolygonStyleAzureOutline EQU 2

; Vertices follow the header
VertX EQU 0
VertY EQU 4
VertZ EQU 8

VertDataSizeALog2 EQU 3
VertDataSizeBLog2 EQU 2
BytesPerVert EQU ((1:SHL:VertDataSizeALog2) + (1:SHL:VertDataSizeBLog2))

; Primitives follow the vertices
PrimVertIndices EQU 0 ; one byte per vertex index
PrimColour EQU 8
PrimSimplifyDist EQU 12
BytesPerPrim EQU 16

; Magic vertex indices
VertexEnd EQU 0
MaxVertexNum EQU 200

; Patterns triggered on the third vertex
VertexThinWhiteLine8Dash EQU &FD
VertexThinWhiteLine16Dash EQU &FE
VertexThickWhiteLine32Dash EQU &FF

; Patterns triggered on the fourth vertex
Vertex32OrangePoints EQU &F8
Vertex16DarkGreyQuads EQU &F9
Vertex64ThickPeruLines EQU &FA
Vertex16ThinBlackZigzags EQU &FB
Vertex8PeridotQuadsCheckZ EQU &FC
Vertex16WhiteQuadsCheckZ EQU &FD
NoCheckZOffset EQU 2
Vertex8PeridotQuads EQU (Vertex8PeridotQuadsCheckZ + NoCheckZOffset)
Vertex16WhiteQuads EQU (Vertex16WhiteQuadsCheckZ + NoCheckZOffset)
; end of Land file format =====================

; Map file format =====================
ObjDataSizeALog2 EQU 5
ObjDataSizeBLog2 EQU 4
BytesPerObj EQU ((1:SHL:ObjDataSizeALog2) + (1:SHL:ObjDataSizeBLog2))

ObjMesh EQU 0
ObjDrawState EQU 4
ObjDist EQU 8
ObjCoord EQU &0C
ObjCoordX EQU &0C
ObjCoordY EQU &10
ObjCoordZ EQU &14
;&18
;&1C
ObjMaxDist EQU &20
ObjFieldOfView EQU &24
ObjCullBackface EQU &28
ObjClipDistFactor EQU &2C

; ObjDist value
ObjDistMax EQU &100000

; ObjDrawState values
ObjDrawStateCull EQU 0
ObjDrawStateDrawIfNear EQU 1
ObjDrawStateDrawn EQU 2

; ObjMesh values
MESH_GROUND_GUN_BASE EQU 0
MESH_STORE_BUILDING EQU 1
MESH_TANK EQU 2
MESH_HEAD_QUARTERS EQU 3
MESH_CONTROL_TOWER EQU 4
MESH_PATROL_BOAT EQU 5
MESH_GREY_CLOUD EQU 13
MESH_WHITE_CLOUD EQU 14
MESH_TIGER_MOTH EQU 18
MESH_FOKKER_V7_TWIN EQU 19
MESH_GOTHA_G_IV_BOMBER EQU 22
MESH_FOKKER_EINDECKER_IV EQU 29
MESH_FOKKER_VIII_TRIPLANE EQU 30
MESH_ALBATROS_DIII_SCOUT EQU 31
MESH_AERODROME_2 EQU 34
MESH_RUBBISH EQU 38
MESH_BRIDGE EQU 46
MESH_ISLAND EQU 48
MESH_AIRCRAFT_CARRIER_2 EQU 50
MESH_AIRCRAFT_CARRIER_3 EQU 51
MESH_AIRCRAFT_CARRIER EQU 52
MESH_YACHT EQU 54
MESH_AERODROME EQU 57
MESH_DARK_OLIVE_FIELD_1 EQU 58
MESH_DARK_OLIVE_FIELD_2 EQU 59
MESH_AVOCADO_FIELD EQU 62
MESH_FACTORY EQU 68
MESH_AIRSHIP EQU 72
MESH_BARRAGE_BALLOON EQU 73
MESH_CARGO_AIRCRAFT EQU 74
MESH_FOKKER_V3_TRIENGINE EQU 75
MESH_FIELD_BOUNDARY EQU 76
MESH_FOKKER_DE5_BIPLANE EQU 77
MESH_CONTROL_TERMINAL EQU 78
MESH_OIL_TANKER EQU 79
MESH_GUN_BOAT EQU 81
MESH_TRAIN EQU 85
MESH_RAILWAY_STATION EQU 87
MESH_SEA EQU 99
MESH_JET_FIGHTER_TARGET EQU 107
MESH_JET_FIGHTER EQU 108
; end of Map file format =====================


ScoreToDeductStopReplay EQU 300
ScorePerBulletOnTarget EQU 5
ScorePerAircraftRevival EQU 100

JSRight EQU 1
JSLeft EQU 2
JSClimb EQU 4
JSDive EQU 8
JSFire EQU &10
JSMask EQU (JSRight+JSLeft+JSClimb+JSDive+JSFire)

ManoeuvreA EQU 0
ManoeuvreB EQU 1
ManoeuvreC EQU 2
ManoeuvreD EQU 3
ManoeuvreE EQU 4
ManoeuvreF EQU 5

MaxAltitudeForManoeuvreB EQU &600000
MaxAltitudeForManoeuvreC EQU &A00000

CarrierMainDeckMinMaxY EQU &32000
CarrierMainDeckMinMaxX EQU &1F4000
CarrierSideDeckMinX EQU &190000
CarrierSideDeckMaxX EQU &C8000
CarrierSideDeckMinY EQU &96000

; These values are purely for the target views
ObjCoordZAirship EQU &1001
AircraftCoordZDefault EQU  &30000 ; exceptions are below
AircraftCoordZAirship EQU &400000
AircraftCoordZTerminal EQU &80000
AircraftCoordZBalloon EQU &200000
AircraftCoordZTanker EQU  &200000
AircraftCoordZGunBoat EQU  &80000

MsgPeriodRepairedRefuelled EQU 2
MsgPeriodTargetDestroyed EQU 20

MaxRangeFireGun EQU &25
MinRangeFixedEngineVolume EQU &50

EngineSoundInterleavePeriodCS EQU 6
EngineSoundRepeatPeriodCS EQU 12
MinCentisecondsPerFrame EQU 6
RefindNearestPlayerInterval EQU 100

ThunderCountdownReinit EQU &0A
FrameCountdownInit EQU &64
FrameCountdownReinit EQU &400

CameraZoomCountdownInit EQU &7F

TimewarpCountdownInit EQU 10
TimewarpCountdownInitB EQU 5

CalcObjVisInterval EQU 5

AircraftCentreZCoord EQU &A000
CarrierDeckZCoord EQU &64000
RunwayZCoord EQU 0
FlakAimHeight EQU &63
FlakGunRange EQU &1400000

BigAircraftBulletCollSizeXY EQU &96000
SmallAircraftBulletCollSizeXY EQU &25800
AircraftBulletCollSizeZ EQU &19000

; It's harder for bullets to hit the player
PlayerBulletCollSizeXYZ EQU &12C00

BigAircraftPlayerCollSizeXY EQU &7D000
SmallAircraftPlayerCollSizeXY EQU &19000
AircraftPlayerCollSizeZ EQU &19000

WaitForVsync EQU &13

DrawPolygonMayDarken EQU 0
DrawPolygonNoDarken EQU 99

GroundFillSrcSize EQU 56

UnitsPerDegree EQU 16
FullRotation EQU (360*UnitsPerDegree)
NearestFullRot EQU (340*UnitsPerDegree)
TwentyDegrees EQU (20*UnitsPerDegree)
ViewTargetRotStep EQU (3*UnitsPerDegree)
ViewAircraftRotStepX EQU (3*UnitsPerDegree)
ViewAircraftRotStepY EQU (4*UnitsPerDegree)
ViewAircraftRotStepZ EQU (8*UnitsPerDegree)
ArrestorHookRotStep EQU (8*UnitsPerDegree)
UnknownAngle EQU (2*UnitsPerDegree)

QuarterTurn EQU (FullRotation/4)
HalfTurn EQU (FullRotation/2)
EncodeShift EQU 5

TwoAndAHalfDegrees EQU (FullRotation/144)
FuelAngle EQU (68*UnitsPerDegree)
AngleShift EQU 10
AngleStepLog2 EQU 2
AngleStepMask EQU (1:SHL:AngleStepLog2)-1

BytesPerWordLog2 EQU 2
WordAlignMask EQU (1:SHL:BytesPerWordLog2)-1

MsgRepairedRefuelled EQU &23
BytesPerMessageString EQU &1F
BytesPerMissionLog2 EQU 6

RowStrideALog2 EQU 8
RowStrideBLog2 EQU 6
RowStride EQU ((1:SHL:RowStrideALog2) + (1:SHL:RowStrideBLog2))
WIDTH EQU RowStride
HEIGHT EQU 256
SPLITHEIGHT EQU (HEIGHT/2)
DASHBOARDWIDTH EQU &50
HeightExclFrontBottomWing EQU (HEIGHT - FrontBottomWingHeight)
FrontTopWingHeight EQU 8
FrontNoseHeight EQU 55
FrontCockpitHeight EQU 28
FrontBottomWingHeight EQU 14
FrontBottomWingPerFrameHeight EQU 2
SideBottomWingHeight EQU 50
SideBottomWingYOffset EQU (HEIGHT - SideBottomWingHeight)
SideTopWingHeight EQU 51
RearHeight EQU 108
RearYOffset EQU (HEIGHT - RearHeight)
CrossHairWidth EQU 70
CrossHairHeight EQU 31
TopBorderHeight EQU 2
ScoreHeight EQU 8

ReplayRecordSize EQU 4
NumDamageBars EQU 7
DamageBarWidth EQU 4
CharWidthLog2 EQU 2
CharHeightLog2 EQU 3
IndexSize EQU 4
ScorePrefixLen EQU 6
ScoreDigitsLen EQU 5
ScoreStringLen EQU (ScorePrefixLen + ScoreDigitsLen)

MouseButtonLeft EQU 4
MouseButtonMiddle EQU 2
MouseButtonRight EQU 1

ReplayStateOff EQU 0
ReplayStateWrite EQU 1
ReplayStateRead EQU 2

NumFramesFullFrontView EQU 2

ViewFront EQU 0
ViewLeft EQU 1
ViewRear EQU 2
ViewRight EQU 3

OutputCollision EQU 0
OutputMissionComplete EQU 1
OutputBadLanding EQU 2
OutputCrashLand EQU 3
OutputQuit EQU 99

NoseWidth EQU 160

ReplayGun EQU 1
ReplayCloseThrottle EQU 2
ReplayOpenThrottle EQU 4
ReplayToggleCrossHair EQU 8
ReplayViewFront EQU &10
ReplayViewLeft EQU &20
ReplayViewBack EQU &40
ReplayViewRight EQU &80
ReplayToggleViewInOut EQU &100
ReplayEnd EQU &2000

SmokeTypeQuickFire EQU 0
SmokeTypeQuickBlack EQU 1
SmokeTypeSlowBlack EQU 2
NumPlayerBullets EQU 141
BytesPerPlayerBullet EQU 32
BytesPerEnemyBullet EQU 32
BytesPerExplosion EQU &18
NumPuffs EQU 3
BytesPerPuff EQU 24
BytesPerSmokeHeader EQU 8
BytesPerSmoke EQU (BytesPerSmokeHeader + (BytesPerPuff * NumPuffs))
QuickSmokeFrames EQU 10
SlowSmokeFrames EQU 30
BytesPerSmokeGen EQU 24
BytesPerFlak EQU 24

NumBullets EQU 200
NumSmokeGen EQU 40

MissionFirstPractice EQU 21
MissionFirstNoTargets EQU 50
MissionFirstRecon EQU 101
MissionDogfight EQU 107

MaxSpeedMissionComplete EQU 10
CrashingAircraftSpeed EQU 11
MaxRefuellingSpeed EQU 10

HitPitchChange EQU 50:SHL:AngleShift
HitRollChange EQU 50:SHL:AngleShift

; A hit has less effect on the player
PlayerHitPitchChange EQU 40:SHL:AngleShift
PlayerHitRollChange EQU 40:SHL:AngleShift

; Sound effects
ChannelGun EQU 1
ChannelEngine1 EQU 2
ChannelEngine2 EQU 3
ChannelMisc EQU 4

VoiceBeep EQU 1
VoiceGun EQU &0A
VoiceWheel EQU &0B
VoiceExplode EQU &0C
VoiceExplodeMD3 EQU &0D
VoiceEngine EQU &0E

MaxVolume EQU &0E
WheelPitch EQU &1800
GunPitch EQU &C00
BeepPitch EQU &5000
ThunderPitch EQU &5A0
ExplosionPitch EQU &1200
BulletHitAircraftPitch EQU &1600
BulletHitGroundTargetPitch EQU &1600
BulletHitPlayerPitch EQU &1200

EngineInsideVolume EQU 10
EngineOutsideVolume EQU 12
ThrottleToEnginePitchLog2 EQU 5
SpeedToEnginePitchLog2 EQU 5


MaxSpans EQU &400

; Colour bit-encoding
RedHi EQU &10
RedLo EQU 4
GreenHi EQU &40
GreenLo EQU &20
BlueHi EQU &80
BlueLo EQU 8
TintHi EQU 2
TintLo EQU 1

MaskByte EQU &83 ; pseudo-colour to be used in masked bitmaps

; Colours
Black EQU 0
BrightRed EQU 23
DarkMaroon EQU 6
DarkNavy EQU 8
Orange EQU &56
Peru EQU &5C
Peridot EQU &74
White EQU &FF
DarkerGrey EQU 3
DarkGrey EQU 45
BrickRed EQU 60
HonoluluBlue EQU &C9
HonoluluBlue2 EQU &CB
Yellow EQU 119
Green EQU 99
MediumRed EQU &14
RoyalAzure EQU &A8
PearlAqua EQU &FA
Olive EQU &25
BrightBlue EQU &8B
DarkSlateBlue EQU &A4
MediumGrey EQU &D0
NapierGreen EQU &64
DarkGreen EQU &20
Honey EQU &57
OffWhite EQU &FD
OffYellow EQU &76
MediumElectricBlue EQU &A3

NumTargets EQU 8
NumPracticeTargets EQU 20
BytesPerTargetLog2 EQU 5
TargetCoordX EQU 0
TargetCoordY EQU 4
TargetCoordZ EQU 8
TargetType EQU &018
TargetHitpoints EQU &01C

MeshToTargetView EQU &64
TargetTypeToMessage EQU &0B
TargetTypeToHitList EQU &32

; TargetType values
TTYPE_GROUND_GUN_BASE EQU 0
TTYPE_STORE_BUILDING EQU 1
TTYPE_TANK EQU 2
TTYPE_HEAD_QUARTERS EQU 3
TTYPE_CONTROL_TOWER EQU 4
TTYPE_PATROL_BOAT EQU 5
TTYPE_AIRSHIP EQU 6
TTYPE_BARRAGE_BALLOON EQU 7
TTYPE_CONTROL_TERMINAL EQU 8
TTYPE_OIL_TANKER EQU 9
TTYPE_GUN_BOAT EQU 10
TTYPE_TRAIN EQU 11
TTYPE_GOTHA_G_IV_BOMBER EQU 12
TTYPE_FOKKER_EINDECKER_IV EQU 13
TTYPE_FOKKER_V7_TWIN EQU 14
TTYPE_FOKKER_V3_TRIENGINE EQU 15
TTYPE_CARGO_AIRCRAFT EQU 16
TTYPE_YACHT EQU 17
TTYPE_RAILWAY_STATION EQU 18
TTYPE_BRIDGE EQU 19
TTYPE_FACTORY EQU 20
TTYPE_AIRCRAFT_CARRIER EQU 21
TTYPE_JET_FIGHTER EQU 22

CameraAngle EQU 0
CameraAngleX EQU 0
CameraAngleY EQU 4
CameraAngleZ EQU 8

CameraPos EQU 12
CameraPosX EQU 12
CameraPosY EQU 16
CameraPosZ EQU 20

NumGaugeNeedles EQU 5

MouseDisabled EQU 0
MouseEnabled EQU 1
MouseDamped EQU 2

NumAircraft EQU 8
NumPracticeAircraft EQU 20

AircraftAngle EQU 0
AircraftPitch EQU 0
AircraftHeading EQU 4
AircraftRoll EQU 8
AircraftAngleW EQU &C

AircraftSpeed EQU &10

AircraftCoord EQU &14
AircraftCoordX EQU &14
AircraftCoordY EQU &18
AircraftCoordZ EQU &1C
AircraftFireGun EQU &20
AircraftViewQuarter EQU &24
AircraftViewAngle EQU &28
AircraftViewIn EQU &02C
AircraftThrottle EQU &030
AircraftUnknown EQU &34
AircraftDamage EQU &038
AircraftScore EQU &03C
AircraftFuel EQU &040
AircraftBackup EQU &44
; 9 words (&68 is first free)
AircraftTargetDist EQU &088
AircraftType EQU &08C
AircraftCtrlX EQU &090
AircraftCtrlY EQU &094
AircraftSerialBitMask EQU &98
AircraftCoordCopy EQU &9C
AircraftCoordCopyX EQU &9C

AircraftCoordCopyY EQU &A0
AircraftCoordCopyZ EQU &A4

AircraftScoreIncrement EQU &A4
AircraftViewMap EQU &A8
AircraftEndManoeuvreCount EQU &A8
AircraftHideMsg EQU &AC
AircraftTargetPtr EQU &AC
AircraftMsgRemain EQU &B0
AircraftMsgNum EQU &B4
; End of aircraft data
BytesPerAircraft EQU &B8

PlayerMinZCoord EQU &B8

PlayerKeys EQU &0BC
PlayerKeyClimb EQU &0BC
PlayerKeyDive EQU &0C0
PlayerKeyLeft EQU &0C4
PlayerKeyRight EQU &0C8
PlayerKeyFire EQU &0CC
PlayerKeyClose EQU &0D0
PlayerKeyOpen EQU &0D4
PlayerKeyCrosshair EQU &0D8
PlayerKeyMap EQU &0DC
PlayerKeyNoMapView EQU &0E0
PlayerKeyFrontView EQU &0E4
PlayerKeyLeftView EQU &0E8
PlayerKeyBackView EQU &0EC
PlayerKeyRightView EQU &0F0
PlayerKeyInOutView EQU &0F4
PlayerKeySwitchCamera EQU &0F8
PlayerKeySwitchCameraB EQU &0FC
PlayerKeyChangeCamDist EQU &100
PlayerKeyResetView EQU &104
PlayerAircraftToView EQU &108
PlayerGhostPlane EQU &10C
PlayerAircraftToViewPtr EQU &110
PlayerCamDistLog2 EQU &114
PlayerCameraPlane EQU &118
PlayerCrossHair EQU &11C
PlayerDebounceCrosshair EQU &120
PlayerDebounceMap EQU &124
PlayerDebounceInOutView EQU &128
PlayerDebounceSwitchCamera EQU &12C
PlayerOtherPlayerPtr EQU &130
PlayerDebounceSwitchCameraB EQU &134
PlayerDebounceChangeCamDist EQU &138
PlayerMapDrawOffset EQU &13C
PlayerMessageCoord EQU &140
PlayerMessageCoordX EQU &140
PlayerMessageCoordY EQU &144
PlayerAircraftToViewB EQU &1F0
PlayerKeyViewNextAircraft EQU &1F4
PlayerDebounceViewNextAircraft EQU &1F8

; Gauge needle positions.
; Keep them in pairs (previous frame and frame before that).
PlayerSpeedoX EQU &150
PlayerSpeedoY EQU &154

PlayerSpeedoOldX EQU &158
PlayerSpeedoOldY EQU &15C

PlayerAltimX EQU &160
PlayerAltimY EQU &164

PlayerAltimOldX EQU &168
PlayerAltimOldY EQU &16C

PlayerAltimShortX EQU &170
PlayerAltimShortY EQU &174

PlayerAltimShortOldX EQU &178
PlayerAltimShortOldY EQU &17C

PlayerCompassX EQU &180
PlayerCompassY EQU &184

PlayerCompassOldX EQU &188
PlayerCompassOldY EQU &18C

PlayerFuelGaugeX EQU &190
PlayerFuelGaugeY EQU &194

PlayerFuelGaugeOldX EQU &198
PlayerFuelGaugeOldY EQU &19C

PlayerSpeedoOrigX EQU &1A0
PlayerSpeedoOrigY EQU &1A4

PlayerAltimOrigX EQU &1A8
PlayerAltimOrigY EQU &1AC

PlayerAltimShortOrigX EQU &1B0
PlayerAltimShortOrigY EQU &1B4

PlayerCompassOrigX EQU &1B8
PlayerCompassOrigY EQU &1BC

PlayerFuelGaugeOrigX EQU &1C0
PlayerFuelGaugeOrigY EQU &1C4

PlayerHighCoord EQU &1C8
PlayerHighCoordX EQU &1C8
PlayerHighCoordY EQU &1CC
PlayerHighCoordZ EQU &1D0

PlayerHighAngle EQU &1D4
PlayerHighAngleY EQU &1D4
PlayerHighAngleX EQU &1D8

PlayerToCameraVec EQU &1DC ; added to PlayerHighCoord
PlayerToCameraVecX EQU &1DC
PlayerToCameraVecY EQU &1E0
PlayerToCameraVecZ EQU &1E4

PlayerRotation EQU &1E8 ; added to PlayerHighAngle
PlayerRotationY EQU &1E8
PlayerRotationX EQU &1EC

QuarterFront EQU 0
QuarterRight EQU 1
QuarterBack EQU 2
QuarterLeft EQU 3

ViewOutside EQU 0
ViewInside EQU 1

CamThisPlayer EQU NumPracticeAircraft
CamOtherPlayer EQU (NumPracticeAircraft+1)
CamLastAircraft EQU &32 ; bug?
CamTarget EQU &64
CamGhost EQU &7B
CamBullet EQU &7C

MaxCamDistLog2 EQU 6

TankSpeed EQU &0F
AirshipSpeed EQU &14
TrainSpeed EQU &2D

AircraftSerialBitOpenThrot EQU 1
AircraftSerialBitCloseThrot EQU 2
AircraftSerialBitFire EQU 4
AircraftSerialBitExit EQU 8
AircraftSerialBitCrash EQU 32
AircraftSerialBitTimewarp EQU &40
AircraftSerialBitMaster EQU &80
AircraftSerialCentre EQU &78

AircraftCtrlMax EQU 100

ATYPE_PLAYER EQU 0
ATYPE_CAMERA EQU 1
ATYPE_FOKKER_V7_TWIN EQU 2
ATYPE_FOKKER_EINDECKER_IV EQU 3
ATYPE_ALBATROS_DIII_SCOUT EQU 4
ATYPE_GOTHA_G_IV_BOMBER EQU 5
ATYPE_FOKKER_VIII_TRIPLANE EQU 6
ATYPE_FOKKER_DE5_BIPLANE EQU 7
ATYPE_FOKKER_V3_TRIENGINE EQU 8
ATYPE_CARGO_AIRCRAFT EQU 9
ATYPE_JET_FIGHTER EQU 10
ATYPE_SPECIAL EQU 99

DamageRepairRate EQU 1
NegMinAircraftDamage EQU 10
FatalAircraftDamage EQU &0B
CrashDamage EQU &0D
CrashDamage2 EQU &0F
ExplodedAircraftDamage EQU &14
DeadAircraftDamage EQU &1E
ExitGameDamage EQU &20
MaxAircraftDamage EQU &23
PracticeReviveAircraftDamage EQU &200
ReviveAircraftDamage EQU &1000000

FuelIncrement EQU &400 ; Rate of refuelling
MinFuel EQU &0A ; Throttle is closed when less than this amount of fuel
InitialFuel EQU &100000 ; Initial amount of fuel

CheatMaxThrottle EQU &1F4
MaxThrottle EQU &64
ThrottleStep EQU &0A ; Rate at which to open/close the throttle

AircraftUnknownDecayLog2 EQU 4
AircraftUnknownMax EQU &2000
ThrottleToFuelLog2 EQU 3 ; Rate of fuel consumption per frame
FrictionLog2 EQU 6 ; Factor by which speed decays per frame
ThrottleToThrustLog2 EQU 4 ; Factor by which speed increases per frame
MinSpeedForArrestorHook EQU &2800
SpeedLossFromArrestorHook EQU &6400

KeySpacebar EQU &62
KeyEnter EQU &3C
KeyReturn EQU &49
KeyF1 EQU &71
KeyF2 EQU &72
KeyF3 EQU &73
KeyF5 EQU &74
KeyF4 EQU &14
KeyF8 EQU &76
KeyF12 EQU &1D
KeyK EQU &46
KeyY EQU &44
KeyP EQU &37
KeyN EQU &55
KeyI EQU &25
KeyE EQU &22
KeyT EQU &23
KeyA EQU &65
KeyF EQU &43
KeyQ EQU &10
Key1 EQU &30
Key2 EQU &31
Key3 EQU &11
Key4 EQU &12
Key5 EQU &13

FixedPointOneLog2 EQU 13
CoordToScreenLog2 EQU 2

MaxThickLineDist EQU &40000
PointClipDist EQU &96
LineClipDist EQU &1E0
LineClipDist2 EQU &78
LineClipDist3 EQU &B4
MaxThickWhiteDashedLineDist EQU &800
MaxThickPeruLineDist EQU &1000
MaxHeightDrawSpecialQuads EQU &190
MaxHeightDrawGroundSpecks EQU &2800
MaxHeightDrawRain EQU &2800
MaxHeightDrawSnow EQU &2800

ExplosionStyleMedium EQU 0
ExplosionStyleHuge EQU &62
ExplosionStyleSmall EQU &63

        ; Conditionally swap registers a and b, overwriting register tmp
        ; as a side-effect
        MACRO
        SWAPIF $cond,$a,$b,$tmp
        MOV$cond $tmp,$a
        MOV$cond $a,$b
        MOV$cond $b,$tmp
        MEND

        ; Swap registers a and b, overwriting register tmp as a side-effect
        MACRO
        SWAP $a,$b,$tmp
        SWAPIF AL,$a,$b,$tmp
        MEND

        ; Find approximately the absolute difference between two numbers
        ; Gives one less than the magnitude of negative numbers (bug?)
        MACRO
        XABSDIFF $res,$a,$b
        SUBS    $res,$a,$b
        MVNMI   $res,$res
        MEND

        ; Find the absolute difference between two numbers
        MACRO
        ABSDIFF $res,$a,$b
        SUBS    $res,$a,$b
        RSBMI   $res,$res,#0
        MEND

        ; Find approximately the absolute magnitude of a number
        ; Gives one less than the magnitude of negative numbers (bug?)
        MACRO
        XABS $n
        CMP     $n,#0
        MVNLT   $n,$n
        MEND

        ; Find the absolute magnitude of a number
        MACRO
        ABS $n
        CMP     $n,#0
        RSBLT   $n,$n,#0
        MEND

        ; Declare an array of pixels to be used as the source for a fill
        MACRO
        MAKEFILL $colour
count SETA 0
        WHILE count < PixelFillChunk
        DCB     $colour
count SETA count + 1
        WEND
        MEND

        ; Copy four pixels with a byte-mask
        MACRO
        DRAWMASKEDQUAD $src,$dst,$allmask,$tmp
        ROUT

        CMP     $src,$allmask
        BEQ     %FT2

        MOV     $tmp,$src,LSR #24
        CMP     $tmp,#MaskByte                         ; ="" (131)
        STRNEB  $tmp,[$dst,#3]
        MOV     $tmp,$src,LSL #8
        MOV     $tmp,$tmp,LSR #24
        CMP     $tmp,#MaskByte                         ; ="" (131)
        STRNEB  $tmp,[$dst,#2]
        MOV     $tmp,$src,LSL #16
        MOV     $tmp,$tmp,LSR #24
        CMP     $tmp,#MaskByte                         ; ="" (131)
        STRNEB  $tmp,[$dst,#1]
        MOV     $tmp,$src,LSL #24
        MOV     $tmp,$tmp,LSR #24
        CMP     $tmp,#MaskByte                         ; ="" (131)
        STRNEB  $tmp,[$dst,#0]
2
        ADD     $dst,$dst,#4
        MEND

        GBLA count

        ORG      &11170

        AREA |ChocksAway|, CODE
        ENTRY


|L00000000.Main_entry_point|
        LDR     R0,|PREFINDNEARESTPLAYERCOUNTER| ; -> Word: &00019994, Entry Point, Main entry point
        MOV     R1,#0
        STR     R1,[R0,#0]

        LDR     R0,|PPICMAP|                  ; -> Word: &00017258
        LDR     R0,[R0,#0]
        STR     R0,|PICMAPCOPY|                  ; -> Word: &00000000

        MOV     R0,#CameraZoomCountdownInit                ; =127
        LDR     R1,|PCAMERAZOOMCOUNTDOWN|                  ; -> Word: &0001C138
        STR     R0,[R1,#0]

        STR     R13,|R13FOREXIT|                 ; -> Word: &00000000, CAUTION: Self Modifying.

        LDR     R0,|CROSSHAIRCOLOURADDR2|                  ; -> Word: &00018984, CAUTION: Self Modifying.
        MOV     R1,#White                         ; ="" (255), CAUTION: Self Modifying.
        STR     R1,[R0,#0]                      ; CAUTION: Self Modifying.

        LDR     R0,|PDAYLANDFILLSRC|                  ; -> Word: &0001BC88, CAUTION: Self Modifying.
        STR     R0,|GROUNDFILLSRCADDR|                  ; -> Word: &00000000, CAUTION: Self Modifying.#

        LDR     R0,|PMISSIONNUM|                  ; -> Word: &000177B8, CAUTION: Self Modifying.
        LDR     R1,[R0,#0]                      ; CAUTION: Self Modifying.

|L00000044|
        LDR     R2,|ENABLETARGETVIEW|                  ; -> Word: &00000000, (Read as data)
        CMP     R2,#1                           ; (Read as data)
        MOVEQ   R1,#0                           ; (Read as data)
        STREQ   R1,[R0,#0]                      ; (Read as data)

        CMP     R1,#3                           ; (Read as data)
        CMPNE   R1,#4                           ; (Read as data)
        CMPNE   R1,#&16                         ; =22, (Read as data)
        CMPNE   R1,#&0D                         ; =13, (Read as data)
        CMPNE   R1,#&0E                         ; =14, (Read as data)
        CMPNE   R1,#&1B                         ; =27, (Read as data)
        CMPNE   R1,#&21                         ; ="!" (33), (Read as data)
        CMPNE   R1,#&67                         ; ="g" (103), (Read as data)
        CMPNE   R1,#&24                         ; ="$" (36), (Read as data)
        CMPNE   R1,#&6A                         ; ="j" (106), (Read as data)
        MOVEQ   R2,#1                           ; (Read as data)
        MOVNE   R2,#0                           ; (Read as data)

        LDR     R3,|PSTARTFROMCARRIER|                  ; -> Word: &00016C3C, (Read as data)
        STR     R2,[R3,#0]

        TST     R1,#1
        LDRNE   R2,|RECONDATAOFFSET|                  ; -> Word: &000010E0
        LDREQ   R2,|EVENMISSIONDATAOFFSET|            ; -> Word: &000021C0

        CMP     R1,#(MissionFirstPractice-1)                         ; =20
        LDRGT   R2,|PRACTICEDATAOFFSET|                  ; -> Word: &000032A0

        CMP     R1,#(MissionFirstRecon-1)                         ; ="d" (100)
        LDRGT   R2,|RECONDATAOFFSET|                  ; -> Word: &000010E0

        LDR     R3,|AIRCRAFTDATAARRAY|                  ; -> Word: MemAircraftDataArray
        ADD     R2,R3,R2 ; source data address
        MOV     R4,#&86                         ; ="" (134)
|COPYAIRCRAFTDATALOOP|
        LDMIA   R2!,{R5-R12}
        STMIA   R3!,{R5-R12}
        SUBS    R4,R4,#1
        BPL     |COPYAIRCRAFTDATALOOP|

        MOV     R2,#FrameCountdownInit         ; ="d" (100)
        STR     R2,|FRAMECOUNTDOWN1024|                  ; -> Word: &00000000

        LDR     R2,|PISNIGHTMISSION|                  ; -> Word: &0001E61C
        MOV     R3,#0
        STR     R3,[R2,#0]

        LDR     R2,|PTHUNDERCOUNTDOWN10|                  ; -> Word: &0001AF88
        STR     R3,[R2,#0]

        CMP     R1,#4
        BGT     |PARSEMISSIONNUM|

|RETFROMMISSIONNUM|
        CMP     R1,#(MissionFirstPractice-1)                         ; =20
        MOVGT   R2,#1 ; practice
        MOVLE   R2,#0 ; not practice

        CMP     R1,#(MissionFirstRecon-1)                         ; ="d" (100)
        MOVGE   R2,#0 ; not practice

        STR     R2,|ISPRACTICEMISSION|                  ; -> Word: &00000000

        LDR     R3,|PGROUNDCOL|                  ; -> Word: &0004A6C0
        MOV     R4,#RoyalAzure
        STRB    R4,[R3,#0]

        CMP     R1,#1
        BNE     |NOTFIRSTMISSION|

        LDR     R0,|AIRCRAFTDATAARRAY|                  ; -> Word: MemAircraftDataArray
        ADD     R0,R0,#BytesPerAircraft*10              ; =&730
        MOV     R1,#0
        STR     R1,[R0,#(AircraftBackup+AircraftCoordX)]                   ; =88
        STR     R1,[R0,#(AircraftBackup+AircraftCoordY)]                   ; =92

|NOTFIRSTMISSION|
        LDR     R2,|ENABLETARGETVIEW|                  ; -> Word: &00000000
        CMP     R2,#1
        BEQ     |INITTARGETVIEWEXTRA|

|INITTARGETVIEWRETURN|
        LDR     R1,|PINITADDRESSES|                  ; -> Word: &00011418
        LDMIA   R1,{R4-R8} ; get aircraft data array,target data array,no. of aircraft?,no. of targets?,zero
        LDR     R11,|PAIRCRAFTDATAARRAYCOPY|                 ; -> Word: &00016C2C
        LDR     R12,|PTARGETDATAARRAY|                 ; -> Word: &0001462C
        STR     R4,[R11,#0] ; aircraft data array pointer
        STR     R5,[R12,#0]

        LDR     R11,|POFFSETTOENDOFAIRCRAFT|                 ; -> Word: &00016C30
        LDR     R12,|PNUMTARGETS|                 ; -> Word: &00014648
        MOV     R4,#BytesPerAircraft                         ; ="" (184)
        MUL     R9,R6,R4 ; multiply by no. of aircraft
        STR     R9,[R11,#0]
        STR     R7,[R12,#0]

        STR     R8,|UNKNOWN2|                  ; -> Word: &00000000
        B       |GAMESTART|                     ; Ends

|RECONDATAOFFSET|
        DCD     &000010E0                       ; Word r/- (referenced)
|EVENMISSIONDATAOFFSET|
        DCD     &000021C0                       ; Word r/- (referenced)
|PRACTICEDATAOFFSET|
        DCD     &000032A0                       ; Word r/- (referenced)
|PREFINDNEARESTPLAYERCOUNTER|
        DCD     |REFINDNEARESTPLAYERCOUNTER|                    ; Word r/- (referenced)
|PPICMAP|
        DCD     |PICMAP|                     ; Word r/- (referenced)
|PICMAPCOPY|
        DCD     &00000000                       ; Word -/w (referenced)
        DCD     |L00008AFC|                     ;~~~ Word -/-
        DCD     |L00008D08|                     ;~~~ Word -/-
|PCAMERAZOOMCOUNTDOWN|
        DCD     |CAMERAZOOMCOUNTDOWN|                       ; Word r/- (referenced)

|PARSEMISSIONNUM|
        CMP     R1,#5
        CMPNE   R1,#6
        CMPNE   R1,#&17                         ; =23
        CMPNE   R1,#&0D                         ; =13
        CMPNE   R1,#&0E                         ; =14
        CMPNE   R1,#&1B                         ; =27
        CMPNE   R1,#&13                         ; =19
        CMPNE   R1,#(MissionFirstPractice-1)             ; =20
        CMPNE   R1,#&1E                         ; =30
        CMPNE   R1,#&21                         ; ="!" (33)
        CMPNE   R1,#&67                         ; ="g" (103)
        CMPNE   R1,#&24                         ; ="$" (36)
        CMPNE   R1,#&6A                         ; ="j" (106)
        LDREQ   R0,|POCEANFILLSRC|                  ; -> Word: &0001BBA8
        STREQ   R0,|GROUNDFILLSRCADDR|                  ; -> Word: &00000000

        CMP     R1,#7
        CMPNE   R1,#8
        CMPNE   R1,#&18                         ; =24
        CMPNE   R1,#&22                         ; =""" (34)
        CMPNE   R1,#&68                         ; ="h" (104)
        LDREQ   R0,|PDESERTFILLSRC|                  ; -> Word: &0001BBE0
        STREQ   R0,|GROUNDFILLSRCADDR|                  ; -> Word: &00000000

        ; Is it an arctic mission?
        CMP     R1,#&0B                         ; =11
        CMPNE   R1,#&0C                         ; =12
        CMPNE   R1,#&1A                         ; =26
        CMPNE   R1,#MissionFirstRecon           ; ="e" (101)
        CMPNE   R1,#&1F                         ; =31
        LDREQ   R0,|PSNOWFILLSRC|                  ; -> Word: &0001BC18
        STREQ   R0,|GROUNDFILLSRCADDR|                  ; -> Word: &00000000
        LDREQ   R0,|CROSSHAIRCOLOURADDR2|                  ; -> Word: &00018984
        MOVEQ   R8,#BrightBlue                         ; ="" (139)
        STREQ   R8,[R0,#0]

        CMP     R1,#&0F                         ; =15
        CMPNE   R1,#&10                         ; =16
        CMPNE   R1,#&1C                         ; =28
        LDREQ   R0,|PNIGHTLANDFILLSRC|                  ; -> Word: &0001BC50
        STREQ   R0,|GROUNDFILLSRCADDR|                  ; -> Word: &00000000
        MOVEQ   R8,#1
        LDREQ   R9,|PISNIGHTMISSION|                  ; -> Word: &0001E61C
        STREQ   R8,[R9,#0]

        B       |RETFROMMISSIONNUM|                     ; Ends

|INITTARGETVIEWEXTRA|
        LDR     R2,|L000002C8|                  ; -> Word: &00000000
        CMP     R2,#&69                         ; ="i" (105)
        CMPNE   R2,#&6D                         ; ="m" (109)
        CMPNE   R2,#&6E                         ; ="n" (110)
        LDREQ   R2,|POCEANFILLSRC|                  ; -> Word: &0001BBA8
        LDRNE   R2,|PDAYLANDFILLSRC|                  ; -> Word: &0001BC88
        STR     R2,|GROUNDFILLSRCADDR|                  ; -> Word: &00000000

        LDR     R3,|PGROUNDCOL|                  ; -> Word: &0004A6C0
        MOVNE   R4,#Olive
        MOVEQ   R4,#RoyalAzure
        STRB    R4,[R3,#0]

        LDR     R3,|PMISSIONNUM|                  ; -> Word: &000177B8
        MOV     R4,#1
        STR     R4,[R3,#0]

        B       |INITTARGETVIEWRETURN|                     ; Ends

|TIMEWARPCOUNTDOWN|
        DCD     &00000000                       ; Word r/w (referenced)
|PSTARTFROMCARRIER|
        DCD     |STARTFROMCARRIER|                      ; Word r/- (referenced)
|PGROUNDCOL|
        DCD     GroundCol                       ; Word r/- (referenced)
|UNKNOWN2|
        DCD     &00000000                       ; Word -/w (referenced)
|CROSSHAIRCOLOURADDR2|
        DCD     |CROSSHAIRCOLOUR|                       ; Word r/- (referenced)
|FRAMECOUNTDOWN1024|
        DCD     &00000000                       ; Word r/w (referenced)
|PISNIGHTMISSION|
        DCD     |ISNIGHTMISSION|
|PTHUNDERCOUNTDOWN10|
        DCD     |THUNDERCOUNTDOWN10|
|PMISSIONNUM|
        DCD     |MISSIONNUM|
|PAIRCRAFTDATAARRAYCOPY|
        DCD     |AIRCRAFTDATAARRAYCOPY|
|PTARGETDATAARRAY|
        DCD     |TARGETDATAARRAY|
|POFFSETTOENDOFAIRCRAFT|
        DCD     |OFFSETTOENDOFAIRCRAFT|
|PNUMTARGETS|
        DCD     |NUMTARGETS|
|PINITADDRESSES|
        DCD     |INITADDRESSES|                ; Word r/- (referenced)
|INITADDRESSES|
|AIRCRAFTDATAARRAY| ; Keep these five words together
        DCD     MemAircraftDataArray ; aircraft data array
        DCD     MemTargetDataArray ; target data array
        DCD     NumPracticeAircraft
        DCD     NumPracticeTargets
        DCD     &00000000                       ;~ Word -/-
|MAXCOORDX3|
        DCD     &000000F0                       ; Word r/w (referenced)
|MAXCOORDY3|
        DCD     &0000007C                       ; Word r/w (referenced)
|ENABLETARGETVIEW|
        DCD     &00000000                       ; Word r/- (referenced)
|L000002C8|
        DCD     &00000000                       ; Word r/- (referenced)
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
|L000002D4|
        DCD     &00000000                       ; Word -/w (referenced)
        DCD     |MISSIONTIMER|
        DCD     |STATICAIRCRAFTVIEWQUARTER|
|R13FOREXIT|
        DCD     &00000000                       ; Word r/w (referenced)

|GAMESTART|
        STR     R14,|RETFROMGAMESTART|                 ; -> Word: &00000000
        STR     R13,|R13ATGAMESTART|                 ; -> Word: &00000000

        MOV     R0,#0
        STR     R0,|PLAYERNUM|                  ; -> Word: &00000000
        BL      |SETPLAYERINFOADDR|

        BL      |INITGAME|
        BL      |INITBOTHPLAYERCOORDSNANGLE|
        BL      |INITBOTHPLAYERKEYS|

        MOV     R0,#0
        STR     R0,|L000002D4|                  ; -> Word: &00000000
        STR     R0,|L00000ED0|                  ; -> Word: &00000000
        STR     R0,|L00000ED4|                  ; -> Word: &00000000
        STR     R0,|TIMEWARPCOUNTDOWN|                  ; -> Word: &00000000

        ; Allow messages
        LDR     R0,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        MOV     R1,#0
        STR     R1,[R0,#AircraftHideMsg]                   ; =172

        LDR     R0,|PPLAYER2INFO3|                  ; -> Word: &00019CB0
        STR     R1,[R0,#AircraftHideMsg]                   ; =172

        LDR     R0,|PSPLITSCREEN|                  ; -> Word: &00016B28
        LDR     R0,[R0,#0]
        CMP     R0,#0
        MOVEQ   R0,#WIDTH
        MOVEQ   R1,#(HEIGHT-1)                  ; ="" (255)
        MOVNE   R0,#&EE                         ; ="" (238)
        MOVNE   R1,#(SPLITHEIGHT-2)                         ; ="~" (126)
        STR     R0,|MAXCOORDX3|                  ; -> Word: &000000F0
        STR     R1,|MAXCOORDY3|                  ; -> Word: &0000007C

        LDR     R0,|ENABLETARGETVIEW|                  ; -> Word: &00000000
        CMP     R0,#1
        BLEQ    |UPDATETARGETVIEW|

|SWAPFRAMEBUFFERS|
        LDR     R0,|FRAMECOUNTDOWN1024|                  ; -> Word: &00000000
        SUBS    R0,R0,#1
        MOVMI   R0,#FrameCountdownReinit                   ; =&400
        STR     R0,|FRAMECOUNTDOWN1024|                  ; -> Word: &00000000

        LDR     R0,|PVDUVARS|                  ; -> Word: &0001514C
        LDR     R2,[R0,#8]
        STR     R2,|FRAMEBUFFER|                  ; -> Word: &00000000

        LDR     R0,|TIMEWARPCOUNTDOWN|                  ; -> Word: &00000000
        CMP     R0,#0
        BGT     |SKIPSWAPFORTIMEWARP|

        LDR     R0,|PVDUVARS|                  ; -> Word: &0001514C
        ADD     R1,R0,#8
        SWI     OS_ReadVduVariables

        LDR     R2,[R0,#8]
        STR     R2,|FRAMEBUFFER|                  ; -> Word: &00000000
        BL      |COPYFRAMEBUFFERADDR|

        LDR     R0,|FRAMEBUFFERNUM|                  ; -> Word: &00000000
        RSB     R0,R0,#1
        STR     R0,|FRAMEBUFFERNUM|                  ; -> Word: &00000000

        CMP     R0,#1
        BEQ     |USE2NDBUFFER|

        MOV     R0,#SetDisplayBuffer                         ; ="q" (113)
        MOV     R1,#1
        SWI     OS_Byte

        MOV     R0,#SetDrawBuffer                         ; ="p" (112)
        MOV     R1,#2
        SWI     OS_Byte

        B       |DONESWAPBUFFERS|                     ; Ends

|USE2NDBUFFER|
        MOV     R0,#SetDisplayBuffer                        ; ="q" (113)
        MOV     R1,#2
        SWI     OS_Byte

        MOV     R0,#SetDrawBuffer                         ; ="p" (112)
        MOV     R1,#1
        SWI     OS_Byte

        B       |DONESWAPBUFFERS|                     ; Ends

|PVDUVARS|
        DCD     |VDUVARS|
|FRAMEBUFFERNUM|
        DCD     &00000000                       ; Word r/w (referenced)
|PPICMAP2|
        DCD     |PICMAP|
|PPLAYERINFO1|
        DCD     |PLAYER1INFO|
        DCD     |ELECTRICBLUESRC|
|PPLAYER2INFO|
        DCD     |PLAYER2INFO|
|PPLAYER1INFO|
        DCD     |PLAYER1INFO|
|P3STATICAIRCRAFTDATA|
        DCD     |STATICAIRCRAFTDATA|
|PAIRCRAFTTOCAMERAVEC|
        DCD     |AIRCRAFTTOCAMERAVEC|
|PAIRCRAFTTYPE|
        DCD     |AIRCRAFTTYPE|
|PPLAYERINFO86|
        DCD     &00000000                       ; Word r/w (referenced)
|PPLAYER2INFO2|
        DCD     |PLAYER2INFO|
|PAIRCRAFTPTRARRAYOFFSET|
        DCD     |AIRCRAFTPTRARRAYOFFSET|
|PDOGFIGHT|
        DCD     |DOGFIGHT|
|PNUMPLAYERS|
        DCD     |NUMPLAYERS|
|POUTPUT|
        DCD     |OUTPUT|

|DONESWAPBUFFERS|
        LDR     R0,|PPLAYER1INFO|                  ; -> Word: &00019AA4
        LDR     R2,[R0,#AircraftRoll]
        CMP     R2,#0
        MOVNE   R2,#1
        STRNE   R2,[R0,#AircraftHideMsg]                   ; =172

        LDR     R0,|PPLAYER2INFO|                  ; -> Word: &00019CB0
        LDR     R2,[R0,#AircraftRoll]
        CMP     R2,#0
        MOVNE   R2,#1
        STRNE   R2,[R0,#AircraftHideMsg]                   ; =172

        MOV     R0,#WaitForVsync                         ; =19
        SWI     OS_Byte

        LDR     R0,|PAIRCRAFTPTRARRAYOFFSET|                  ; -> Word: &00012D94
        MOV     R1,#0
        STR     R1,[R0,#0]

|SKIPSWAPFORTIMEWARP|
        LDR     R10,|ENABLETARGETVIEW|                 ; -> Word: &00000000
        CMP     R10,#1
        BEQ     |NOPLAYERCTRL|

        ; Deal with player 1 (always local)
        MOV     R0,#0
        STR     R0,|PLAYERNUM|                  ; -> Word: &00000000
        BL      |SETPLAYERINFOADDR|

        LDR     R0,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDR     R1,[R0,#AircraftCtrlX]                   ; =144
        LDR     R2,[R0,#AircraftCtrlY]                   ; =148
        STR     R0,|PPLAYERINFO86|                  ; -> Word: &00000000
        BL      |READKEYS|

        LDR     R3,[R0,#AircraftDamage]                   ; =56
        CMP     R3,#FatalAircraftDamage                         ; =11
        STRLT   R1,[R0,#AircraftCtrlX]                   ; =144
        STRLT   R2,[R0,#AircraftCtrlY]                   ; =148

        LDR     R0,|PNUMPLAYERS|                  ; -> Word: &0001A03C
        LDR     R0,[R0,#0]
        CMP     R0,#1
        BEQ     |FINISHEDPLAYERCTRL| ; It's a one-player game

        ; It's a two-player game
        LDR     R0,|PSPLITSCREEN|                  ; -> Word: &00016B28
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BEQ     |ISSERIALLINK| ; Other player is remote

        ; It's a two-player game with split screen
        MOV     R0,#1
        STR     R0,|PLAYERNUM|                  ; -> Word: &00000000
        BL      |SETPLAYERINFOADDR|

        LDR     R0,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDR     R1,[R0,#AircraftCtrlX]                   ; =144
        LDR     R2,[R0,#AircraftCtrlY]                   ; =148
        BL      |READKEYS|

        LDR     R3,[R0,#AircraftDamage]                   ; =56
        CMP     R3,#FatalAircraftDamage                         ; =11
        STRLT   R1,[R0,#AircraftCtrlX]                   ; =144
        STRLT   R2,[R0,#AircraftCtrlY]                   ; =148

        B       |FINISHEDPLAYERCTRL|                     ; Ends

|ISSERIALLINK|
        ; It's a two-player game via serial link
        MOV     R0,#1
        STR     R0,|PLAYERNUM|                  ; -> Word: &00000000
        BL      |SETPLAYERINFOADDR|

        LDR     R0,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDR     R1,|PPLAYERINFO86|                  ; -> Word: &00000000
        BL      |DOSERIALLINK|

|FINISHEDPLAYERCTRL|
        MOV     R0,#0
        STR     R0,|PLAYERNUM|                  ; -> Word: &00000000
        BL      |SETPLAYERINFOADDR|

        LDR     R0,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDR     R0,[R0,#AircraftSerialBitMask]                   ; =152
        TST     R0,#AircraftSerialBitExit
        BEQ     |NOEXIT|

        LDR     R0,|POUTPUT|                  ; -> Word: &00017A54
        MOV     R1,#OutputQuit
        STR     R1,[R0,#0]
        B       |EXITGAME|                     ; Ends

|NOEXIT|
        LDR     R0,|PNUMPLAYERS|                  ; -> Word: &0001A03C
        LDR     R0,[R0,#0]
        CMP     R0,#1
        BGT     |TWOPLAYERSOALLOWCTRL|

        LDR     R0,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        MOV     R1,#0
        STR     R1,[R0,#AircraftSerialBitMask]                   ; =152

|TWOPLAYERSOALLOWCTRL|
        ; bug: pointless
        MOV     R0,#0
        STR     R0,|PLAYERNUM|                  ; -> Word: &00000000

        ; bug: pointless
        LDR     R0,|TIMEWARPCOUNTDOWN|                  ; -> Word: &00000000
        CMP     R0,#0
        BGT     |SKIPINITPLAYERNUMFORTIMEWARP|

|NOPLAYERCTRL|
        MOV     R0,#0
        STR     R0,|PLAYERNUM|                  ; -> Word: &00000000

|SKIPINITPLAYERNUMFORTIMEWARP|
        BL      |SETPLAYERINFOADDR|

        LDR     R0,|PSPLITSCREEN|                  ; -> Word: &00016B28
        LDR     R0,[R0,#0]
        CMP     R0,#0
        MOVEQ   R0,#HEIGHT                      ; =&100
        MOVNE   R0,#(SPLITHEIGHT-2)                         ; ="~" (126)
        STR     R0,|MAXCOORDY3|                  ; -> Word: &0000007C
        LDR     R0,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        BL      |INITDRAWINGFORGAME|

        LDR     R0,|MAXCOORDY4|                  ; -> Word: &00000000
        STR     R0,|MAXCOORDY3|                  ; -> Word: &0000007C
        BL      |SETVIEWIFDEAD|

        LDR     R11,|PPICMAP2|                 ; -> Word: &00017258
        LDR     R11,[R11,#0]
        CMP     R11,#0
        LDREQ   R11,|ENABLETARGETVIEW|                 ; -> Word: &00000000
        CMPEQ   R11,#0
        BNE     |PICMAPORTARGETVIEW|

        LDR     R0,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDR     R1,[R0,#AircraftCtrlX]                   ; =144
        LDR     R2,[R0,#AircraftCtrlY]                   ; =148
        BL      |SERVICEPLAYERAIRCRAFT|

        LDR     R0,|PPLAYER2INFO2|                  ; -> Word: &00019CB0
        LDR     R1,[R0,#AircraftCtrlX]                   ; =144
        LDR     R2,[R0,#AircraftCtrlY]                   ; =148
        BL      |SERVICEPLAYERAIRCRAFT|

|PICMAPORTARGETVIEW|
        LDR     R12,|PPLAYERINFO2|                 ; -> Word: &00019AA4
        BL      |SERVICEGHOSTPLANE|

        LDR     R0,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDR     R3,[R0,#AircraftTargetDist]                   ; =136
        CMP     R3,#1
        MOVEQ   R3,#0
        STREQ   R3,[R0,#AircraftPitch]
        MVNEQ   R3,#&64                         ; ="d" (100)
        STREQ   R3,[R0,#AircraftRoll]
        STREQ   R3,[R0,#AircraftAngleW]                   ; =12

        LDR     R0,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDMIA   R0,{R1-R12} ; get AircraftAngle, AircraftSpeed, AircraftCoord, AircraftFireGun...

        LDR     R0,[R0,#PlayerAircraftToViewPtr]                   ; =272
        ADD     R0,R0,#AircraftViewQuarter                      ; ="$" (36)
        LDMIA   R0,{R10-R12} ; overwrite AircraftViewQuarter, AircraftViewAngle, AircraftViewIn
        BL      |AMENDAIRCRAFTANGLES|

        LDR     R14,|PAIRCRAFTTYPE|                 ; -> Word: &000188D4
        LDR     R14,[R14,#0]
        LDR     R0,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        STR     R14,[R0,#AircraftType]                  ; =140

        LDR     R0,|P3STATICAIRCRAFTDATA|                  ; -> Word: &00012328
        MOV     R1,R1,ASR #AngleShift
        MOV     R2,R2,ASR #AngleShift
        MOV     R3,R3,ASR #AngleShift
        MOV     R4,R4,ASR #AngleShift
        MOV     R5,R5,ASR #AngleShift
        BIC     R1,R1,#AngleStepMask
        BIC     R2,R2,#AngleStepMask
        BIC     R3,R3,#AngleStepMask
        BIC     R4,R4,#AngleStepMask
        STMIA   R0,{R1-R12}

        MOV     R0,#0
        STR     R0,|L00001170|                  ; -> Word: &00000000
        STR     R0,|L00001178|                  ; -> Word: &00000000

        LDR     R0,|PAIRCRAFTTOCAMERAVEC|                  ; -> Word: &00018B88
        MOV     R1,#0
        MOV     R2,#0
        MOV     R3,#0
        STMIA   R0,{R1-R3}

        LDR     R0,|STATICAIRCRAFTVIEWQUARTER|                  ; -> Word: &00000000
        CMP     R0,#ViewLeft
        MOVEQ   R1,#QuarterTurn                      ; =&5A0
        MOVLT   R1,#0
        CMP     R0,#ViewRear
        MOVEQ   R1,#HalfTurn                      ; =&B40
        MOVGT   R1,#(QuarterTurn*3):SHR:EncodeShift         ; ="" (135)
        MOVGT   R1,R1,LSL #EncodeShift
        STR     R1,|STATICAIRCRAFTVIEWANGLE|                  ; -> Word: &00000000

        LDR     R1,|MAXCOORDY4|                  ; -> Word: &00000000
        LDR     R0,|PSTATICAIRCRAFTDATA|                  ; -> Word: &00012328
        LDR     R2,|FRAMEBUFFER|                  ; -> Word: &00000000
        BL      |COPYDATA|

        LDR     R3,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDR     R5,|PSTATICAIRCRAFTCOORD|                  ; -> Word: &0001233C
        LDR     R6,|PAIRCRAFTTOCAMERAVEC2|                  ; -> Word: &00018B88
        BL      |COPYADDR|

        BL      |DOENGINESOUND|

        BL      |SETAIRCRAFTTYPE|

        LDR     R1,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDR     R1,[R1,#PlayerAircraftToViewPtr]                   ; =272
        LDR     R1,[R1,#AircraftViewIn]                   ; =44
        CMP     R1,#ViewInside
        BLNE    |UPDATEEXTERNALCAM|

        LDR     R0,|PLAYERNUM|                  ; -> Word: &00000000
        LDR     R1,|L000009F0|                  ; -> Word array: &00000000
        CMP     R0,R1
        BNE     |NOTARGETS|

        BL      |INITOBJMESHADDR|

        LDR     R0,|PDOGFIGHT|                  ; -> Word: &00016C38
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BNE     |NOTARGETS|

        BL      |SERVICETARGETS|
        BL      |MOVETARGETS|

        LDR     R10,|ENABLETARGETVIEW|                 ; -> Word: &00000000
        CMP     R10,#1
        BEQ     |L0000075C|

|NOTARGETS|
        BL      |DRAWAIRCRAFTVIEWFORPLAYER1|

        LDR     R0,|PLAYERNUM|                  ; -> Word: &00000000
        LDR     R1,|L000009F0|                  ; -> Word array: &00000000
        CMP     R0,R1
        BNE     |MAINGAMELOOP|

        LDR     R0,|PDOGFIGHT|                  ; -> Word: &00016C38
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BNE     |ISDOGFIGHT|

        BL      |REFINDNEARESTPLAYER|
        BL      |SERVICEALLAIRCRAFTWRAP|
        BL      |DRAWALLAIRCRAFT|

|ISDOGFIGHT|
        LDR     R0,|TIMEWARPCOUNTDOWN|                  ; -> Word: &00000000
        CMP     R0,#0
        BGT     |MAINGAMELOOP|

        LDR     R0,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDR     R0,[R0,#AircraftViewMap]                   ; =168
        CMP     R0,#0
        BNE     |MAINGAMELOOP| ; displaying the map for player 2

        LDR     R10,|PPLAYER2INFO3|                 ; -> Word: &00019CB0
        BL      |DRAWAIRCRAFTVIEWFORPLAYER|

|L0000075C|
        LDR     R10,|ENABLETARGETVIEW|                 ; -> Word: &00000000
        CMP     R10,#1
        BLEQ    |VIEWTARGET|

        MOV     R0,#FlushBuffer                         ; =21
        MOV     R1,#0
        SWI     OS_Byte

        MOV     R0,#SplitCursors
        SWI     OS_WriteC

        LDR     R13,|R13FOREXIT|                 ; -> Word: &00000000

        LDR     R0,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        BL      |DRAWSCENEFORPLAYER|

        B       |MAINGAMELOOP|                     ; Ends

|AIRCRAFTISUPSIDEDOWN2|
        DCD     &00000000                       ; Word -/w (referenced)

|DRAWSCENEFORPLAYER|
        ; r0 = player info
        LDR     R0,[R0,#PlayerAircraftToViewPtr]                   ; =272, Function entry, (alters flags)
        STR     R0,|AIRCRAFTPTR|                  ; -> Word array: &00000000
        STMFD   R13!,{R0-R12,R14}

        LDR     R1,[R0,#AircraftDamage]                   ; =56
        CMP     R1,#FatalAircraftDamage                   ; =11
        BLE     |NOSPINPLAYER|

        LDR     R1,[R0,#AircraftHeading]
        ADD     R1,R1,#TwoAndAHalfDegrees:SHL:AngleShift      ; =&A000
        CMP     R1,#FullRotation:SHL:AngleShift               ; =&5A0000
        SUBGT   R1,R1,#FullRotation:SHL:AngleShift            ; =&5A0000
        STR     R1,[R0,#AircraftHeading]

|NOSPINPLAYER|
        ; r0 = aircraft data
        BL      |DOENGINESOUND|

        LDR     R1,|PSPLITSCREEN|                  ; -> Word: &00016B28
        LDR     R1,[R1,#0]
        CMP     R1,#0
        LDRNE   R1,|PPREVENTTIMESKIP|                  ; -> Word: &00015714
        STRNE   PC,[R1,#0] ; no time skip if split screen

        LDMIA   R0,{R1-R12}

        LDR     R0,|THREEQUARTERTURN3|                  ; -> Word array: &00438000
        CMP     R1,R0
        MOVGT   R0,#0
        MOVLT   R0,#1
        CMP     R1,#QuarterTurn:SHL:AngleShift                      ; =&168000
        MOVLT   R0,#0
        STR     R0,|AIRCRAFTISUPSIDEDOWN2|                  ; -> Word: &00000000

        CMP     R12,#0
        BEQ     |L0000083C|
        CMP     R10,#0
        BEQ     |L0000083C|
        CMP     R10,#2
        BEQ     |L0000083C|

        CMP     R0,#1
        RSBEQ   R3,R3,#0
        CMP     R3,#0
        ADDLT   R3,R3,#FullRotation:SHL:AngleShift                   ; =&5A0000
        CMP     R3,#QuarterTurn:SHL:AngleShift                      ; =&168000
        BLT     |L0000083C|

        LDR     R0,|THREEQUARTERTURN3|                  ; -> Word array: &00438000
        CMP     R3,R0
        BGT     |L0000083C|

        RSB     R1,R1,#0
        CMP     R1,#0
        ADDLT   R1,R1,#FullRotation:SHL:AngleShift                   ; =&5A0000

|L0000083C|
        LDR     R0,|FRAMEBUFFER|                  ; -> Word: &00000000
        LDR     R12,|AIRCRAFTPTR|                 ; -> Word array: &00000000

        SWAP    R1,R2,R11

        MOV     R1,R1,ASR #AngleShift
        MOV     R2,R2,ASR #AngleShift
        MOV     R3,R3,ASR #AngleShift

        BIC     R1,R1,#AngleStepMask
        BIC     R2,R2,#AngleStepMask
        BIC     R3,R3,#AngleStepMask

        LDR     R6,[R12,#AircraftViewAngle]                  ; =40
        ADD     R1,R1,R6
        CMP     R1,#FullRotation                      ; =&1680
        SUBGT   R1,R1,#FullRotation                   ; =&1680

        LDR     R6,[R12,#AircraftViewQuarter]                  ; =36
        CMP     R6,#QuarterRight
        CMPNE   R6,#QuarterLeft

        SWAPIF  EQ,R2,R3,R7

        CMP     R6,#1
        CMPNE   R6,#2
        RSBEQ   R2,R2,#FullRotation                   ; =&1680

        CMP     R6,#2
        RSBGE   R3,R3,#FullRotation                   ; =&1680

        LDR     R6,[R12,#AircraftViewIn]                  ; =44
        CMP     R6,#ViewOutside
        BNE     |L000008C8|

        LDR     R2,|PSPLITSCREEN|                  ; -> Word: &00016B28
        LDR     R2,[R2,#0]
        CMP     R2,#1
        MOVEQ   R2,#&C8   ; CameraAngleY = 200
        MOVNE   R2,#&19,28  ; CameraAngleY =&190
        MOV     R3,#0 ; CameraAngleZ

|L000008C8|
        ; Compute the camera's coordinates relative to the plane
        LDR     R4,[R12,#AircraftCoordX]                  ; =20
        LDR     R5,[R12,#AircraftCoordY]                  ; =24
        LDR     R6,[R12,#AircraftCoordZ]                  ; =28

        LDR     R7,|PAIRCRAFTTOCAMERAVEC2|                  ; -> Word: &00018B88
        LDMIA   R7,{R7-R9}

        ADD     R4,R4,R7 ; camera position
        ADD     R5,R5,R8
        ADD     R6,R6,R9

        ADR     R9,|CAMERA|                  ; -> Word array: &00000000
        STMIA   R9,{R1-R6}

        MVN     R4,R4,ASR #10
        MVN     R5,R5,ASR #10
        MVN     R6,R6,ASR #10

        LDR     R12,|PISNIGHTMISSION|                 ; -> Word: &0001E61C
        LDR     R12,[R12,#4]
        CMP     R12,#0

        LDR     R11,|MAXCOORDX3|                 ; -> Word: &000000F0
        LDR     R12,|MAXCOORDY4|                 ; -> Word: &00000000
        LDR     R10,|GROUNDFILLSRCADDR|                 ; -> Word: &00000000
        ADDNE   R10,R10,#|DAYLANDFILLSRC| - |NIGHTLANDFILLSRC|  ; ="8" (56)
        BL      |DRAWSCENE|

        BL      |DOENGINESOUND| ; bug? Already done this

        LDMFD   R13!,{R0-R12,R14}
        MOV     PC,R14                          ; Function exit, Ends

|SERVICEGHOSTPLANE|
        ; r12 = player info
        LDR     R0,[R12,#PlayerAircraftToView]                  ; =264, Function entry, (alters flags)
        CMP     R0,#CamGhost                         ; ="{" (123)
        MOVNE   PC,R14                          ; Function exit if NE

        STR     R14,|RETFROMSERVICEGHOSTPLANE|                 ; -> Word: &00000000
        STR     R12,|PLAYERINFOTEMP|                 ; -> Word: &00000000

        LDR     R0,[R12,#PlayerGhostPlane]                  ; =268
        LDR     R1,[R0,#AircraftCtrlX]                   ; =144
        LDR     R2,[R0,#AircraftCtrlY]                   ; =148
        MOV     R3,#&19,20                      ; =&19000
        STR     R3,[R0,#AircraftSpeed]                   ; =16
        BL      |SERVICEPLAYERAIRCRAFT|

        LDR     R12,|PLAYERINFOTEMP|                 ; -> Word: &00000000
        LDR     R0,[R12,#PlayerGhostPlane]                  ; =268

        LDR     R1,[R0,#AircraftThrottle]                   ; =48
        MOV     R1,R1,LSL #10
        STR     R1,[R0,#AircraftSpeed]                   ; =16

        BL      |UPDATEAIRCRAFTCOORDS|

        LDR     R12,|PLAYERINFOTEMP|                 ; -> Word: &00000000
        LDR     R0,[R12,#PlayerGhostPlane]                  ; =268
        MOV     R1,#0
        STR     R1,[R0,#AircraftSpeed]                   ; =16

        LDR     R0,[R12,#PlayerGhostPlane]                  ; =268
        MOV     R1,#InitialFuel                 ; =&100000
        STR     R1,[R0,#AircraftFuel]                   ; =1<<6

        MOV     R1,#0
        STR     R1,[R0,#AircraftUnknown]                   ; =52

        LDR     R1,[R0,#AircraftPitch]
        STR     R1,[R0,#AircraftAngleW]                   ; =12

        LDR     R1,[R0,#AircraftCoordZ]                   ; =28
        CMP     R1,#AircraftCentreZCoord               ; =&A000
        MVNLT   R1,#AircraftCentreZCoord               ; =&A000
        STR     R1,[R0,#AircraftCoordZ]                   ; =28

        MOV     R1,#0
        STR     R1,[R0,#AircraftDamage]                   ; =56

        LDR     R14,|RETFROMSERVICEGHOSTPLANE|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|PPLAYER2INFO3|
        DCD     |PLAYER2INFO|
|PSPLITSCREEN|
        DCD     |SPLITSCREEN|
|RETFROMSERVICEGHOSTPLANE|
        DCD     &00000000                       ; Word r/w (referenced)
|PLAYERINFOTEMP|
        DCD     &00000000                       ; Word r/w (referenced)
|PPREVENTTIMESKIP|
        DCD     |PREVENTTIMESKIP|
|CAMERA|; Angles
        DCD     &00000000                       ; Word array -/w (referenced)
        DCD     &00000000                       ;~~~ Word array -/w
        DCD     &00000000                       ;~~~ Word array -/w
        ; Coordinates
        DCD     &00000000                       ;~~~ Word array -/w
        DCD     &00000000                       ;~~~ Word array -/w
        DCD     &00000000                       ;~~~ Word array -/w

        DCD     |PLAYER1INFO|
        DCD     &00000000                       ;~~~ Word array -/-
|AIRCRAFTPTR|
        DCD     &00000000                       ;~~~ Word array r/w (referenced)
|L000009F0|
        DCD     &00000000                       ;~~~ Word array r/- (referenced)
|THREEQUARTERTURN3|
        DCD     (3*QuarterTurn):SHL:AngleShift                       ;~~~ Word array r/- (referenced)
        DCD     |CLIPDIST|
        DCD     &0000A000                       ;~~~ Word array -/-
|SCOREOFFSET|
        DCD     (HEIGHT-ScoreHeight)*RowStride      ;~~~ Word array r/- (referenced)
|PNUMOBJMINUS1|
        DCD     |NUMOBJMINUS1|
        DCD     &00000000                       ;~~~ Word array -/-
|PUNKNOWN|
        DCD     |UNKNOWN|

|MAINGAMELOOP|
        BL      |EXITGAMEIFPLAYERSDEAD|

        LDR     R0,|PLAYERNUM|                  ; -> Word: &00000000
        LDR     R1,|L000009F0|                  ; -> Word array: &00000000
        CMP     R0,R1
        BNE     |NOTINSIDEFRONTVIEW2|

        ; bug? seems to be unused
        LDR     R0,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDR     R0,[R0,#0]
        CMP     R0,#0
        LDREQ   R0,|PUNKNOWN|                  ; -> Word array: &00018E48
        MOVEQ   R1,#0
        STREQ   R1,[R0,#0]

        LDR     R0,|PNUMOBJMINUS1|                  ; -> Word array: &0001C7E0
        LDR     R1,[R0,#4] ; load ANOTHERNUMOBJMINUS1
        STR     R1,[R0,#0] ; store as NUMOBJMINUS1

        BL      |SERVICEPLAYERBULLETS|
        BL      |ZEROSOMETHINGIFNOTPRACTICE|

        LDR     R0,|ISPRACTICEMISSION|                  ; -> Word: &00000000
        CMP     R0,#0
        BLEQ    |SERVICEENEMYBULLETS|

        BL      |SERVICESMOKE|
        BL      |SERVICEEXPLOSIONS|
        BL      |THUNDER|
        BL      |DRAWBORDERS|

        LDR     R0,|ENABLETARGETVIEW|                  ; -> Word: &00000000
        CMP     R0,#1
        BEQ     |NORIGHTVIEW|

        BL      |COPYPLAYERCOORDS|

        LDR     R0,|ISPRACTICEMISSION|                  ; -> Word: &00000000
        CMP     R0,#1
        BEQ     |NOMISSIONOBJECTIVE|

        BL      |SERVICEMISSION|

|NOMISSIONOBJECTIVE|
        BL      |CHECKAIRCRAFTCOLLISION|

        LDR     R1,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDR     R0,[R1,#AircraftDamage]                   ; =56
        CMP     R0,#FatalAircraftDamage                         ; =11
        BGE     |NOTINSIDEFRONTVIEW2|

        LDR     R1,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDR     R0,[R1,#PlayerAircraftToView]                   ; =264
        CMP     R0,#CamThisPlayer                         ; =20
        BNE     |NOTINSIDEFRONTVIEW2|

        LDR     R0,[R1,#AircraftViewIn]                   ; =44
        CMP     R0,#ViewInside
        BNE     |NOTINSIDEFRONTVIEW2|

        LDR     R0,|TIMEWARPCOUNTDOWN|                  ; -> Word: &00000000
        CMP     R0,#0
        BGT     |NOTINSIDEFRONTVIEW2|

        LDR     R0,|STATICAIRCRAFTVIEWQUARTER|                  ; -> Word: &00000000
        BL      |DRAWCOCKPIT|

        LDR     R1,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDR     R0,[R1,#AircraftViewQuarter]                   ; =36
        CMP     R0,#QuarterFront
        BNE     |NOTINSIDEFRONTVIEW2|

        LDR     R0,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDR     R0,[R0,#AircraftViewMap]                   ; =168
        CMP     R0,#0
        BNE     |NOTINSIDEFRONTVIEW2|

        BL      |DRAWCROSSHAIR|

        LDR     R0,|PSPLITSCREEN3|                  ; -> Word: &00016B28
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BNE     |NOTINSIDEFRONTVIEW2|

        LDR     R0,|FRAMEBUFFER|                  ; -> Word: &00000000
        ADD     R0,R0,#(10*RowStride)                   ; =&C80
        STR     R0,|FRAMEBUFFER|                  ; -> Word: &00000000
        BL      |DRAWGAUGES|

        LDR     R0,|FRAMEBUFFER|                  ; -> Word: &00000000
        SUB     R0,R0,#(10*RowStride)                   ; =&C80
        STR     R0,|FRAMEBUFFER|                  ; -> Word: &00000000

        LDR     R0,|FRAMEBUFFER|                  ; -> Word: &00000000
        LDR     R1,|SCOREOFFSET|                  ; -> Word array: &00013600
        ADD     R0,R0,R1

        LDR     R1,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDR     R1,[R1,#AircraftScore]                   ; =60
        CMP     R1,#0
        MOVLT   R1,#0
        BL      |DRAWSCORE|

        LDR     R0,|FRAMEBUFFER|                  ; -> Word: &00000000
        LDR     R1,|SCOREOFFSET|                  ; -> Word array: &00013600
        ADD     R0,R0,R1
        ADD     R0,R0,#&46,30                   ; =&118
        LDR     R1,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDR     R1,[R1,#AircraftDamage]                   ; =56
        BL      |DRAWDAMAGE|

|NOTINSIDEFRONTVIEW2|
        LDR     R1,|COUNT0TO2|                  ; -> Word: &00000000
        ADD     R1,R1,#1
        CMP     R1,#3
        MOVGE   R1,#0
        STR     R1,|COUNT0TO2|                  ; -> Word: &00000000

|PLAYERNUMLOOP|
        LDR     R0,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDR     R1,[R0,#AircraftDamage]                   ; =56
        CMP     R1,#&22                         ; =""" (34)
        MOVGE   R1,#&21                         ; ="!" (33)
        STRGE   R1,[R0,#AircraftDamage]                   ; =56
        CMP     R1,#ExplodedAircraftDamage             ; =20
        BGE     |NEXTPLAYER|

        ADD     R1,R0,#AircraftCoord                      ; =20
        LDMIA   R1,{R1-R3} ; get x,y,z
        STR     R3,|AIRCRAFTHEIGHT|                  ; -> Word: &00000000
        LDR     R4,|COSINE|                  ; -> Word: MemCosine
        LDR     R5,|SINE|                  ; -> Word: MemSine

        LDR     R6,[R0,#AircraftAngleW]                   ; =12
        MOV     R6,R6,ASR #12
        MOV     R6,R6,LSL #BytesPerWordLog2

        LDR     R7,[R0,#AircraftHeading]
        MOV     R7,R7,ASR #12
        MOV     R7,R7,LSL #BytesPerWordLog2

        LDR     R8,[R4,R7] ; cosine
        LDR     R9,[R5,R7] ; sine
        LDR     R10,[R4,R6] ; cosine
        LDR     R11,[R5,R6] ; sine
        MUL     R12,R8,R10
        MOV     R8,R12,ASR #2
        MUL     R12,R9,R10
        MOV     R9,R12,ASR #2

        LDR     R4,|CHEATACCUM|                  ; -> Word: &00000000
        LDR     R10,|CHEATFLAG|                 ; -> Word: &00000063
        ADD     R4,R4,R10
        CMP     R4,#1
        MOV     R4,#0
        STR     R4,|CHEATACCUM|                  ; -> Word: &00000000

        LDR     R4,[R0,#AircraftSpeed]                   ; =16
        MOV     R4,R4,ASR #AngleShift
        MUL     R10,R9,R4
        MOVNE   R10,R10,ASR #12
        MOVEQ   R10,R10,ASR #9 ; cheat
        ADD     R1,R1,R10

        MUL     R10,R8,R4
        MOVNE   R10,R10,ASR #12
        MOVEQ   R10,R10,ASR #9 ; cheat
        SUB     R2,R2,R10

        MUL     R10,R11,R4
        SUBNE   R3,R3,R10,ASR #2
        SUBEQ   R3,R3,R10,LSL #1 ; cheat

        MOV     R12,#AircraftCentreZCoord              ; =&A000
        STR     R12,[R0,#PlayerMinZCoord]                  ; =184

        CMP     R3,#AircraftCentreZCoord               ; =&A000
        LDRLT   R12,|AIRCRAFTHEIGHT|                 ; -> Word: &00000000
        BLLT    |CHECKRUNWAYLANDING|

        LDR     R12,|AIRCRAFTHEIGHT|                 ; -> Word: &00000000
        BL      |CHECKCARRIERLANDING|

        ADD     R0,R0,#AircraftCoord                      ; =20
        STMIA   R0,{R1-R3} ; store x,y,z coords
|NEXTPLAYER|
        LDR     R0,|PLAYERNUM|                  ; -> Word: &00000000
        CMP     R0,#1
        BEQ     |FINISHEDPLAYERLOOP|

        MOV     R0,#1
        STR     R0,|PLAYERNUM|                  ; -> Word: &00000000

        BL      |SETPLAYERINFOADDR|
        B       |PLAYERNUMLOOP|                     ; Ends

|FINISHEDPLAYERLOOP|
        MOV     R0,#0
        STR     R0,|PLAYERNUM|                  ; -> Word: &00000000

        BL      |SETPLAYERINFOADDR|

        LDR     R0,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDR     R0,[R0,#PlayerAircraftToView]                   ; =264
        CMP     R0,#CamThisPlayer                         ; =20
        BNE     |NORIGHTVIEW|

        LDR     R0,|STATICAIRCRAFTVIEWIN|                  ; -> Word: &00000001
        CMP     R0,#ViewInside
        BNE     |NORIGHTVIEW|

        LDR     R0,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDR     R0,[R0,#AircraftViewMap]                   ; =168
        CMP     R0,#0
        BNE     |NORIGHTVIEW|

        LDR     R0,|PSPLITSCREEN3|                  ; -> Word: &00016B28
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BNE     |NORIGHTVIEW|

        LDR     R0,|STATICAIRCRAFTVIEWQUARTER|                  ; -> Word: &00000000
        CMP     R0,#ViewLeft
        BNE     |NOLEFTVIEW|

        ; Draw interplane struts (left view)
        MVN     R0,#&78                         ; ="x" (120)
        MOV     R1,#&57,30                      ; =&15C
        MOV     R2,#&16                         ; =22
        MVN     R3,#&57,30                      ; =&15C
        MOV     R4,#Black
        BL      |DRAW2DLINE|

        MVN     R0,#&74                         ; ="t" (116)
        MOV     R1,#&57,30                      ; =&15C
        MOV     R2,#&1A                         ; =26
        MVN     R3,#&57,30                      ; =&15C
        MOV     R4,#Black
        BL      |DRAW2DLINE|

        MOV     R0,#&96                         ; ="" (150)
        MOV     R1,#&57,30                      ; =&15C
        MOV     R2,#&49,30                      ; =&124
        MVN     R3,#&57,30                      ; =&15C
        MOV     R4,#Black
        BL      |DRAW2DLINE|

        MOV     R0,#&9A                         ; ="" (154)
        MOV     R1,#&57,30                      ; =&15C
        MOV     R2,#&4A,30                      ; =&128
        MVN     R3,#&57,30                      ; =&15C
        MOV     R4,#Black
        BL      |DRAW2DLINE|

|NOLEFTVIEW|
        LDR     R0,|STATICAIRCRAFTVIEWQUARTER|                  ; -> Word: &00000000
        CMP     R0,#ViewRight
        BNE     |NORIGHTVIEW|

        ; Draw interplane struts (right view)
        MOV     R0,#&78                         ; ="x" (120)
        MOV     R1,#&57,30                      ; =&15C
        MVN     R2,#&16                         ; =22
        MVN     R3,#&57,30                      ; =&15C
        MOV     R4,#Black
        BL      |DRAW2DLINE|

        MOV     R0,#&74                         ; ="t" (116)
        MOV     R1,#&57,30                      ; =&15C
        MVN     R2,#&1A                         ; =26
        MVN     R3,#&57,30                      ; =&15C
        MOV     R4,#Black
        BL      |DRAW2DLINE|

        MVN     R0,#&96                         ; ="" (150)
        MOV     R1,#&57,30                      ; =&15C
        MVN     R2,#&49,30                      ; =&124
        MVN     R3,#&57,30                      ; =&15C
        MOV     R4,#Black
        BL      |DRAW2DLINE|

        MVN     R0,#&9A                         ; ="" (154)
        MOV     R1,#&57,30                      ; =&15C
        MVN     R2,#&4A,30                      ; =&128
        MVN     R3,#&57,30                      ; =&15C
        MOV     R4,#Black
        BL      |DRAW2DLINE|

|NORIGHTVIEW|
        LDR     R0,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDR     R1,[R0,#AircraftViewMap]                   ; =168
        CMP     R1,#0
        BNE     |NODISPLAY|

        BL      |DISPLAYDEMO|
        BL      |DISPLAYMSG|

|NODISPLAY|
        LDR     R0,|PSPLITSCREEN3|                  ; -> Word: &00016B28
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BLNE    |DOSERIALGAME|

        LDR     R0,|CHEATFLAG|                  ; -> Word: &00000063
        CMP     R0,#0
        BNE     |NEXTPLAYER2|

        ; Player is cheating
        LDR     R0,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDR     R1,[R0,#AircraftDamage]                   ; =56
        CMP     R1,#ExplodedAircraftDamage         ; =20
        BLT     |NEXTPLAYER2|

        ; Cheating player's aircraft has exploded: reset it
        MOV     R1,#0
        STR     R1,[R0,#AircraftPitch]
        STR     R1,[R0,#AircraftRoll]
        STR     R1,[R0,#AircraftAngleW]                   ; =12
        STR     R1,[R0,#AircraftViewQuarter]                   ; =36

        MVN     R1,#&02,22                      ; =&800
        STR     R1,[R0,#AircraftDamage]                   ; =56

        MOV     R1,#&32                         ; ="2" (50)
        STR     R1,[R0,#AircraftThrottle]                   ; =48

        MOV     R1,R1,LSL #10
        STR     R1,[R0,#AircraftSpeed]                   ; =16

        MOV     R1,#ViewInside
        STR     R1,[R0,#AircraftViewIn]                   ; =44

        LDR     R1,[R0,#AircraftCoordZ]                   ; =28
        ADD     R1,R1,#&02,12                   ; =&200000
        STR     R1,[R0,#AircraftCoordZ]                   ; =28

|NEXTPLAYER2|
        LDR     R0,|PLAYERNUM|                  ; -> Word: &00000000
        ADD     R0,R0,#1
        STR     R0,|PLAYERNUM|                  ; -> Word: &00000000

        CMP     R0,#1 ; bug?
        B       |SWAPFRAMEBUFFERS|                     ; Ends

|L00000E1C|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
|CHEATACCUM|
        DCD     &00000000                       ; Word r/w (referenced)
|CHEATFLAG|
        DCD     &00000063                       ; Word r/- (referenced)
|RETFROMGAMESTART|
        DCD     &00000000                       ; Word r/w (referenced)
|COUNT0TO2|
        DCD     &00000000                       ; Word r/w (referenced)
        DCD     |FLAKARRAYOFFSET|
|AIRCRAFTHEIGHT|
        DCD     &00000000                       ; Word r/w (referenced)
|R13ATGAMESTART|
        DCD     &00000000                       ; Word -/w (referenced)
|ISPRACTICEMISSION|
        DCD     &00000000                       ; Word r/w (referenced)
|GROUNDFILLSRCADDR|
        DCD     &00000000                       ; Word r/w (referenced)
|PDAYLANDFILLSRC|
        DCD     |DAYLANDFILLSRC|
|POCEANFILLSRC|
        DCD     |OCEANFILLSRC|
|PDESERTFILLSRC|
        DCD     |DESERTFILLSRC|
|PSNOWFILLSRC|
        DCD     |SNOWFILLSRC|
|PNIGHTLANDFILLSRC|
        DCD     |NIGHTLANDFILLSRC|

|ROTATE|
        ; R6,R7 = x,y (updated)
        ; R11 = angle
        ; x = (y * cos(angle)) +
        ;     (x * cos(angle + 360))
        ; y = (x * sine(angle)) +
        ;     (y * sine(angle - 360))
        CMP     R11,#FullRotation                     ; =&1680, Function entry, (alters flags)
        SUBGT   R11,R11,#FullRotation                 ; =&1680
        LDR     R8,|COSINE|                  ; -> Word: MemCosine
        LDR     R12,[R8,R11]
        MUL     R5,R12,R7
        MOV     R5,R5,ASR #12

        ADD     R11,R11,#QuarterTurn                 ; =&5A0
        LDR     R12,[R8,R11]
        MUL     R9,R12,R6
        MOV     R9,R9,ASR #12

        ADD     R10,R9,R5

        LDR     R8,|SINE|                  ; -> Word: MemSine
        LDR     R12,[R8,R11]
        MUL     R5,R12,R6
        MOV     R5,R5,ASR #12

        SUB     R11,R11,#QuarterTurn                 ; =&5A0
        LDR     R12,[R8,R11]
        MUL     R9,R12,R7
        MOV     R9,R9,ASR #12

        ADD     R6,R9,R5

        MOV     R7,R10

        MOV     PC,R14                          ; Function exit, Ends

|PLAYERNUM|
        DCD     &00000000                       ; Word r/w (referenced)
|L00000ED0|
        DCD     &00000000                       ; Word -/w (referenced)
|L00000ED4|
        DCD     &00000000                       ; Word -/w (referenced)
|PPLAYERINFO2|
        DCD     |PLAYER1INFO|
|FRAMEBUFFER|
        DCD     &00000000                       ; Word r/w (referenced)
|MAXCOORDY4|
        DCD     &00000000                       ; Word r/w (referenced)
        DCD     &00000000                       ;~ Word -/-
|MAXCOORDY5|
        DCD     &00000000                       ; Word -/w (referenced)

|DRAW2DLINE|
        ; R0,R1 = start coords
        ; R2,R3 = end coords
        ; R4 = colour
        STR     R14,|RETFROMDRAW2DLINE|       ; -> Word: &00000000, Function entry, (alters flags)
        LDR     R10,|MAXCOORDX3|                 ; -> Word: &000000F0
        LDR     R12,|MAXCOORDY3|                 ; -> Word: &0000007C

        ; Translate coordinate origin to the middle of the screen
        ADD     R0,R0,R10,LSL #(CoordToScreenLog2-1)
        MOV     R0,R0,ASR #CoordToScreenLog2
        ADD     R2,R2,R10,LSL #(CoordToScreenLog2-1)
        MOV     R2,R2,ASR #CoordToScreenLog2

        ADD     R1,R1,R12,LSL #(CoordToScreenLog2-1)
        ADD     R3,R3,R12,LSL #(CoordToScreenLog2-1)
        MOV     R3,R3,ASR #CoordToScreenLog2
        MOV     R1,R1,ASR #CoordToScreenLog2

        MOV     R11,#0
        STR     R11,|CLIPLINECOORDSLOOPCOUNT|                 ; -> Word: &00000000

        LDR     R11,|PTMPSTORE3|                 ; -> Word: &0001898C
|CLIPLINECOORDSLOOP|
        CMP     R0,#1
        BLT     |LEFTCLIPX|

|LEFTCLIPX0DONE|
        CMP     R0,R10
        BGT     |RIGHTCLIPX|

|RIGHTCLIPX0DONE|
        CMP     R1,#0
        BLT     |TOPCLIPY|

|TOPCLIPY0DONE|
        CMP     R1,R12
        BGT     |BOTCLIPY|

|BOTCLIPY0DONE|
        LDR     R9,|CLIPLINECOORDSLOOPCOUNT|                  ; -> Word: &00000000
        CMP     R9,#1
        BEQ     |CLIPLINECOORDSFINISHED|

        MOV     R9,#1
        STR     R9,|CLIPLINECOORDSLOOPCOUNT|                  ; -> Word: &00000000

        SWAP    R0,R2,R6 ; swap x0,x1
        SWAP    R1,R3,R6 ; swap y0,y1

        B       |CLIPLINECOORDSLOOP|                     ; Ends

|CLIPLINECOORDSFINISHED|
        CMP     R0,R2 ; compare x0,x1
        BNE     |L00000F84|

        CMP     R1,R3 ; compare y0,y1
        SUBEQ   R0,R0,#1

|L00000F84|
        CMP     R0,R2 ; compare x0,x1

        SWAPIF  GT,R0,R2,R5 ; swap x0,x1
        SWAPIF  GT,R1,R3,R5 ; swap y0,y1

        SUB     R7,R2,R0
        SUB     R8,R3,R1
        MOV     R9,R7
        MOV     R10,R8
        ABS     R9
        ABS     R10
        CMP     R9,R10
        BLT     |L00001014|

        STMFD   R13!,{R0-R4}
        MOV     R1,R7
        MOV     R8,R8,LSL #FixedPointOneLog2
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R12,R3
        LDMFD   R13!,{R0-R4}
        MOV     R1,R1,LSL #FixedPointOneLog2

        LDR     R11,|FRAMEBUFFER|                 ; -> Word: &00000000
        MOV     R9,#RowStride
|L00000FEC|
        ADD     R10,R11,R0
        MOV     R3,R1,ASR #FixedPointOneLog2
        MUL     R8,R3,R9
        ADD     R10,R10,R8
        STRB    R4,[R10,#0]
        ADD     R1,R1,R12
        ADD     R0,R0,#1
        CMP     R0,R2
        BLE     |L00000FEC|

        B       |FINISHEDDRAW2DLINE|                     ; Ends

|L00001014|
        CMP     R1,R3
        RSBGT   R8,R8,#0

        STMFD   R13!,{R0-R4}
        MOV     R1,R8
        MOV     R8,R7,LSL #FixedPointOneLog2
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R12,R3
        LDMFD   R13!,{R0-R4}
        MOV     R0,R0,LSL #FixedPointOneLog2
        CMP     R1,R3
        MVNGT   R7,#0
        MOVLE   R7,#1

        LDR     R11,|FRAMEBUFFER|                 ; -> Word: &00000000
        MOV     R9,#RowStride
|L0000104C|
        ADD     R10,R11,R0,ASR #FixedPointOneLog2
        MOV     R2,R1
        MUL     R8,R2,R9
        ADD     R10,R10,R8
        STRB    R4,[R10,#0]
        ADD     R1,R1,R7
        ADD     R0,R0,R12
        CMP     R1,R3
        BNE     |L0000104C|

|FINISHEDDRAW2DLINE|
        LDR     R14,|RETFROMDRAW2DLINE|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|LEFTCLIPX|
        CMP     R2,#1
        BLT     |FINISHEDDRAW2DLINE|

        STMFD   R13!,{R0-R4}
        SUB     R8,R2,#1
        MOV     R8,R8,LSL #FixedPointOneLog2
        SUB     R1,R2,R0
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R5,R3
        LDMFD   R13!,{R0-R4}
        MOV     R0,#1
        SUB     R6,R3,R1
        MUL     R7,R5,R6
        MOV     R7,R7,ASR #FixedPointOneLog2
        SUB     R1,R3,R7
        B       |LEFTCLIPX0DONE|                     ; Ends

|RIGHTCLIPX|
        CMP     R2,R10
        BGT     |FINISHEDDRAW2DLINE|

        STMFD   R13!,{R0-R4}
        RSB     R8,R2,R10
        MOV     R8,R8,LSL #FixedPointOneLog2
        SUB     R1,R0,R2
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R5,R3
        LDMFD   R13!,{R0-R4}
        MOV     R0,R10
        SUB     R6,R3,R1
        MUL     R7,R5,R6
        MOV     R7,R7,ASR #FixedPointOneLog2
        SUB     R1,R3,R7
        B       |RIGHTCLIPX0DONE|                     ; Ends

|TOPCLIPY|
        CMP     R3,#0
        BLT     |FINISHEDDRAW2DLINE|

        STMFD   R13!,{R0-R4}
        SUB     R8,R3,#0
        MOV     R8,R8,LSL #FixedPointOneLog2
        SUB     R1,R3,R1
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R5,R3
        LDMFD   R13!,{R0-R4}
        MOV     R1,#0
        SUB     R6,R2,R0
        MUL     R7,R5,R6
        MOV     R7,R7,ASR #FixedPointOneLog2
        SUB     R0,R2,R7
        B       |TOPCLIPY0DONE|                     ; Ends

|BOTCLIPY|
        CMP     R3,R12
        BGT     |FINISHEDDRAW2DLINE|

        STMFD   R13!,{R0-R4}
        RSB     R8,R3,R12
        MOV     R8,R8,LSL #FixedPointOneLog2
        SUB     R1,R1,R3
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R5,R3
        LDMFD   R13!,{R0-R4}

        LDR     R1,|MAXCOORDY4|                  ; -> Word: &00000000
        SUB     R1,R1,#1
        SUB     R6,R2,R0
        MUL     R7,R5,R6
        MOV     R7,R7,ASR #FixedPointOneLog2
        SUB     R0,R2,R7
        B       |BOTCLIPY0DONE|                     ; Ends

|L0000116C|
        DCD     &00000000                       ;~ Word -/-
|L00001170|
        DCD     &00000000                       ; Word -/w (referenced)
        DCD     &00000000                       ;~ Word -/-
|L00001178|
        DCD     &00000000                       ; Word -/w (referenced)
        DCD     &00000000                       ;~ Word -/-
|UNUSEDDIVIDENDA|
        DCD     &0000927C                       ;~~~ Word -/-
        DCD     &000249F0                       ;~~ Word -/-
        DCD     &00124F80                       ;~~~ Word -/-
        DCD     &00927C00                       ;~~~ Word -/-
|RETFROMDRAW2DLINE|
        DCD     &00000000                       ; Word r/w (referenced)
        DCD     &00000000                       ;~ Word -/-
|PSTATICAIRCRAFTCOORD|
        DCD     |STATICAIRCRAFTCOORD|
|PTMPSTORE3|
        DCD     |TMP|
        DCD     &00000000                       ;~ Word -/-
        DCD     |EXPLOSIONPARAMS|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
|PSTATICAIRCRAFTDATA|
        DCD     |STATICAIRCRAFTDATA|
; ------------
|STATICAIRCRAFTDATA|
        DCD     &00000000 ; AircraftPitch
        DCD     &00000168 ; AircraftRoll
        DCD     &00000000 ; AircraftHeading
        DCD     &00000000 ; AircraftAngleW
        DCD     &00000064 ; AircraftSpeed
|STATICAIRCRAFTCOORD|
        DCD     &0C106100 ; AircraftCoordX
        DCD     &00000000 ; AircraftCoordY
        DCD     &0000C800 ; AircraftCoordZ
|STATICAIRCRAFTFIREGUN|
        DCD     &00000000 ; AircraftFireGun
|STATICAIRCRAFTVIEWQUARTER|
        DCD     &00000000 ; AircraftViewQuarter
|STATICAIRCRAFTVIEWANGLE|
        DCD     &00000000 ; AircraftViewAngle
|STATICAIRCRAFTVIEWIN|
        DCD     ViewInside ; AircraftViewIn
; ------------
        DCD     &00000000                       ;~ Word -/-
|L000011EC|
        DCD     &00000000                       ;~ Word -/-
|L000011F0|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
|COSINE|
        DCD     MemCosine                       ; Word r/- (referenced)
|SINE|
        DCD     MemSine                       ; Word r/- (referenced)
        DCD     &00000000                       ;~ Word -/-
|CLIPLINECOORDSLOOPCOUNT|
        DCD     &00000000                       ; Word r/w (referenced)
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
|PAIRCRAFTTOCAMERAVEC2|
        DCD     |AIRCRAFTTOCAMERAVEC|

|INITDRAWINGFORGAME|
        LDR     R1,[R0,#AircraftViewIn]                   ; =44, Function entry, (alters flags)
        CMP     R1,#ViewOutside
        BEQ     |L00001248|

        LDR     R1,[R0,#PlayerAircraftToView]                   ; =264
        CMP     R1,#CamThisPlayer                         ; =20
        BNE     |L00001248|

        LDR     R1,[R0,#AircraftViewQuarter]                   ; =36
        CMP     R1,#QuarterFront
        MOVEQ   R2,#&F3                         ; ="" (243)
        MOVEQ   R3,#1
        BNE     |L00001248|

        B       |L00001250|                     ; Ends

|L00001248|
        MOV     R2,#(HEIGHT-2)                         ; ="" (254)
        MOV     R3,#0
|L00001250|
        LDR     R12,|PENABLETARGETVIEW|                 ; -> Word: &00011434
        LDR     R12,[R12,#0]
        CMP     R12,#0
        MOVNE   R2,#&D8                         ; ="" (216)
        MOVNE   R3,#1

        LDR     R4,|MAXCOORDY3|                  ; -> Word: &0000007C
        CMP     R2,R4
        MOVGT   R2,R4
        STR     R2,|MAXCOORDY4|                  ; -> Word: &00000000

        STR     R3,|MAXCOORDY5|                  ; -> Word: &00000000

        MOV     PC,R14                          ; Function exit, Ends

|PENABLETARGETVIEW|
        DCD     |ENABLETARGETVIEW|
        DCD     &00000000                       ;~ Word -/-

|INITDRAWINGFORMAP|
        STR     R14,|RETFROMINITDRAW|                 ; -> Word: &00000000, Function entry, (alters flags)
        MOV     R2,#(HEIGHT-1)                         ; ="" (255)
        MOV     R3,#0
        STR     R2,|MAXCOORDY4|                  ; -> Word: &00000000
        STR     R3,|MAXCOORDY5|                  ; -> Word: &00000000

        BL      |DUPFRAMEBUFFERADDR|

        LDR     R14,|RETFROMINITDRAW|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|L000012A4|
        DCD     &00000000                       ;~ Word -/-
|RETFROMINITDRAW|
        DCD     &00000000                       ; Word r/w (referenced)
|PPICMAP3|
        DCD     |PICMAP|
|PSPLITSCREEN2|
        DCD     |SPLITSCREEN|

|EXITGAME|
        LDR     R13,|R13FOREXIT|                 ; -> Word: &00000000

        MOV     R0,#FlushBuffer                         ; =21
        MOV     R1,#0 ; all
        SWI     OS_Byte

        MOV     R0,#SplitCursors
        SWI     OS_WriteC

        LDR     R0,|PPICMAP3|                  ; -> Word: &00017258
        MOV     R1,#0
        STR     R1,[R0,#0]

        ; Init PlayerHighCoord
        MOV     R0,#&7D,14                      ; =&1F40000
        MVN     R1,#&FA,16                      ; =&FA0000
        MOV     R2,#&01,10                      ; =&400000

        ; Init PlayerHighAngle
        MOV     R3,#&FA,18                      ; =&3E8000
        MOV     R4,#&C8                         ; ="" (200)

        LDR     R5,|PPLAYER1INFO4|                  ; -> Word: &00019AA4
        ADD     R5,R5,#PlayerHighCoord                   ; =&1C8
        STMIA   R5,{R0-R4} ; Store PlayerHighCoord and PlayerHighAngle

        LDR     R5,|PPLAYER2INFO4|                  ; -> Word: &00019CB0
        ADD     R5,R5,#PlayerHighCoord                   ; =&1C8
        STMIA   R5,{R0-R4} ; Store PlayerHighCoord and PlayerHighAngle

        LDR     R0,|PPICMAPCOPY|                  ; -> Word: &000112F0
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BEQ     |DORETFROMGAMESTART|

        LDR     R0,|PAIRCRAFTTOCAMERAVEC3|                  ; -> Word: &00018B88
        LDMIA   R0,{R10-R12} ; Load movement vector

        LDR     R5,|PSPLITSCREEN2|                  ; -> Word: &00016B28
        LDR     R5,[R5,#AircraftPitch]
        CMP     R5,#0
        MOVEQ   R5,#&19,18                      ; =&64000
        MOVNE   R5,#&32000                      ; =&32000

        LDR     R0,|PPLAYER1INFO4|                  ; -> Word: &00019AA4
        ADD     R1,R0,#AircraftCoord                      ; =20
        LDMIA   R1,{R1-R3}

        ADD     R1,R1,R10 ; Add movement vector
        ADD     R2,R2,R11
        ADD     R3,R3,R12

        LDR     R4,[R0,#AircraftHeading]
        ADD     R4,R4,#QuarterTurn:SHL:AngleShift                   ; =&168000
        MOV     R9,R4 ; y angle
        ADD     R0,R0,#PlayerHighCoord                   ; =&1C8
        STMIA   R0,{R1-R5} ; store x,y,z coords and y,x angles

        LDR     R0,|PPLAYER2INFO4|                  ; -> Word: &00019CB0
        MOV     R4,R9 ; y angle
        ADD     R0,R0,#PlayerHighCoord                   ; =&1C8
        STMIA   R0,{R1-R5} ; store x,y,z coords and y,x angles

|DORETFROMGAMESTART|
        MOV     R0,R9 ; y angle
        LDR     R14,|RETFROMGAMESTART|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|PPLAYER1INFO4|
        DCD     |PLAYER1INFO|
|PPLAYER2INFO4|
        DCD     |PLAYER2INFO|
|PAIRCRAFTTOCAMERAVEC3|
        DCD     |AIRCRAFTTOCAMERAVEC|
|PPICMAPCOPY|
        DCD     |PICMAPCOPY|

|DRAWGAUGES|
        STR     R14,|RETFROMDRAWGAUGES|                 ; -> Word: &00000000, Function entry, (alters flags)
        LDR     R0,|MAXCOORDY4|                  ; -> Word: &00000000
        STR     R0,|MAXCOORDY6|                  ; -> Word: &00000000

        MOV     R0,#(HEIGHT-2)                         ; ="" (254)
        STR     R0,|MAXCOORDY4|                  ; -> Word: &00000000

        LDR     R12,|PPLAYERINFO2|                 ; -> Word: &00019AA4
        LDR     R0,[R12,#PlayerSpeedoOrigX] ; load start coords
        LDR     R1,[R12,#PlayerSpeedoOrigY]                  ; =420
        LDR     R2,[R12,#PlayerSpeedoOldX] ; load end coords
        LDR     R3,[R12,#PlayerSpeedoOldY]                  ; =348
        MOV     R4,#DarkSlateBlue                         ; ="" (164)
        BL      |DRAW2DLINE|

        LDR     R12,|PPLAYERINFO2|                 ; -> Word: &00019AA4
        LDR     R0,[R12,#PlayerAltimOrigX] ; load start coords
        LDR     R1,[R12,#PlayerAltimOrigY]                  ; =428
        LDR     R2,[R12,#PlayerAltimOldX] ; load end coords
        LDR     R3,[R12,#PlayerAltimOldY]                  ; =364
        MOV     R4,#DarkSlateBlue                         ; ="" (164)
        BL      |DRAW2DLINE|

        LDR     R12,|PPLAYERINFO2|                 ; -> Word: &00019AA4
        LDR     R0,[R12,#PlayerAltimShortOrigX] ; load start coords
        LDR     R1,[R12,#PlayerAltimShortOrigY]                  ; =436
        LDR     R2,[R12,#PlayerAltimShortOldX] ; load end coords
        LDR     R3,[R12,#PlayerAltimShortOldY]                  ; =380
        MOV     R4,#DarkSlateBlue                         ; ="" (164)
        BL      |DRAW2DLINE|

        LDR     R12,|PPLAYERINFO2|                 ; -> Word: &00019AA4
        LDR     R0,[R12,#PlayerCompassOrigX] ; load start coords
        LDR     R1,[R12,#PlayerCompassOrigY]                  ; =444
        LDR     R2,[R12,#PlayerCompassOldX] ; load end coords
        LDR     R3,[R12,#PlayerCompassOldY]                  ; =396
        MOV     R4,#DarkSlateBlue                         ; ="" (164)
        BL      |DRAW2DLINE|

        LDR     R12,|PPLAYERINFO2|                 ; -> Word: &00019AA4
        LDR     R0,[R12,#PlayerFuelGaugeOrigX] ; load start coords
        LDR     R1,[R12,#PlayerFuelGaugeOrigY]                  ; =452
        LDR     R2,[R12,#PlayerFuelGaugeOldX] ; load end coords
        LDR     R3,[R12,#PlayerFuelGaugeOldY]                  ; =412
        MOV     R4,#DarkSlateBlue                         ; ="" (164)
        BL      |DRAW2DLINE|

        ; Because redraw is double-buffered, we need to maintain a history of two
        ; previous states for every needle on every gauge. Copy the previous frame's
        ; state over the state of the frame before that.
        LDR     R12,|PPLAYERINFO2|                 ; -> Word: &00019AA4
        ADD     R12,R12,#PlayerSpeedoX   ; =&150
        MOV     R11,#(NumGaugeNeedles-1)
|COPYPREVFRAMENEEDLEPOSLOOP|
        LDMIA   R12!,{R0,R1}
        STMIA   R12!,{R0,R1}
        SUBS    R11,R11,#1
        BPL     |COPYPREVFRAMENEEDLEPOSLOOP|

        LDR     R12,|PPLAYERINFO2|                 ; -> Word: &00019AA4
        LDR     R0,[R12,#AircraftSpeed]                  ; =16
        MOV     R0,R0,ASR #AngleShift
        MOV     R0,R0,LSL #5
        SUB     R0,R0,#(QuarterTurn/2)                ; =&2D0
        ADD     R0,R0,#FullRotation                   ; =&1680
|ANGLEMOD360LOOP|
        CMP     R0,#FullRotation                      ; =&1680
        SUBGT   R0,R0,#FullRotation                   ; =&1680
        BGT     |ANGLEMOD360LOOP|

        LDR     R1,|COSINE|                  ; -> Word: MemCosine
        LDR     R2,|SINE|                  ; -> Word: MemSine
        LDR     R3,[R1,R0]
        LDR     R4,[R2,R0]

        MVN     R3,R3,ASR #7
        ADD     R3,R3,R3,ASR #1
        MVN     R4,R4,ASR #7
        ADD     R4,R4,R4,ASR #1

        LDR     R0,[R12,#PlayerSpeedoOrigX] ; load start coords
        LDR     R1,[R12,#PlayerSpeedoOrigY]                  ; =420
        ADD     R3,R3,R0
        ADD     R4,R4,R1
        STR     R3,[R12,#PlayerSpeedoX] ; store end coords
        STR     R4,[R12,#PlayerSpeedoY]                  ; =340

        MOV     R2,R3 ; end coords
        MOV     R3,R4
        MOV     R4,#Black
        BL      |DRAW2DLINE| ; draw speedometer needle

        LDR     R12,|PPLAYERINFO2|                 ; -> Word: &00019AA4
        LDR     R0,[R12,#AircraftCoordZ]                  ; =28
        MOV     R0,R0,ASR #AngleShift
        BIC     R0,R0,#AngleStepMask
|ANGLEMOD360LOOP4|
        CMP     R0,#FullRotation                      ; =&1680
        SUBGT   R0,R0,#FullRotation                   ; =&1680
        BGT     |ANGLEMOD360LOOP4|

        LDR     R1,|COSINE|                  ; -> Word: MemCosine
        LDR     R2,|SINE|                  ; -> Word: MemSine
        LDR     R4,[R1,R0]
        LDR     R3,[R2,R0]

        MOV     R3,R3,ASR #7
        ADD     R3,R3,R3,ASR #1
        MVN     R4,R4,ASR #7
        ADD     R4,R4,R4,ASR #1

        LDR     R0,[R12,#PlayerAltimOrigX] ; load start coords
        LDR     R1,[R12,#PlayerAltimOrigY]                  ; =428
        ADD     R3,R3,R0
        ADD     R4,R4,R1
        STR     R3,[R12,#PlayerAltimX] ; store end coords
        STR     R4,[R12,#PlayerAltimY]                  ; =356

        MOV     R2,R3 ; end coords
        MOV     R3,R4
        MOV     R4,#Black
        BL      |DRAW2DLINE| ; draw altimeter needle

        LDR     R12,|PPLAYERINFO2|                 ; -> Word: &00019AA4
        LDR     R0,[R12,#AircraftCoordZ]                  ; =28
        MOV     R0,R0,ASR #AngleShift+3
        SUB     R0,R0,R0,ASR #2
        BIC     R0,R0,#AngleStepMask
|ANGLEMOD360LOOP2|
        CMP     R0,#FullRotation                      ; =&1680
        SUBGT   R0,R0,#FullRotation                   ; =&1680
        BGT     |ANGLEMOD360LOOP2|

        LDR     R1,|COSINE|                  ; -> Word: MemCosine
        LDR     R2,|SINE|                  ; -> Word: MemSine
        LDR     R4,[R1,R0]
        LDR     R3,[R2,R0]

        MOV     R3,R3,ASR #7
        MVN     R4,R4,ASR #7

        LDR     R0,[R12,#PlayerAltimShortOrigX] ; load start coords
        LDR     R1,[R12,#PlayerAltimShortOrigY]                  ; =436
        ADD     R3,R3,R0
        ADD     R4,R4,R1
        STR     R3,[R12,#PlayerAltimShortX] ; store end coords
        STR     R4,[R12,#PlayerAltimShortY]                  ; =372

        MOV     R2,R3 ; end coords
        MOV     R3,R4
        MOV     R4,#PearlAqua                         ; ="" (250)
        BL      |DRAW2DLINE| ; draw altimeter needle

        LDR     R12,|PPLAYERINFO2|                 ; -> Word: &00019AA4
        LDR     R0,[R12,#AircraftHeading]
        MOV     R0,R0,ASR #AngleShift
        BIC     R0,R0,#AngleStepMask

        LDR     R1,[R12,#AircraftType]                  ; =140
        CMP     R1,#ATYPE_CAMERA
        SUBEQ   R0,R0,#HalfTurn                   ; =&B40
        CMP     R0,#0
        ADDLT   R0,R0,#FullRotation                   ; =&1680
        CMP     R0,#FullRotation                      ; =&1680
        SUBGT   R0,R0,#FullRotation                   ; =&1680

        LDR     R1,|COSINE|                  ; -> Word: MemCosine
        LDR     R2,|SINE|                  ; -> Word: MemSine
        LDR     R4,[R1,R0]
        LDR     R3,[R2,R0]

        MOV     R3,R3,ASR #8
        ADD     R3,R3,R3,ASR #1
        MOV     R4,R4,ASR #8
        ADD     R4,R4,R4,ASR #1

        LDR     R0,[R12,#PlayerCompassOrigX] ; load start coords
        LDR     R1,[R12,#PlayerCompassOrigY]                  ; =444
        ADD     R3,R3,R0
        ADD     R4,R4,R1
        STR     R3,[R12,#PlayerCompassX] ; store end coords
        STR     R4,[R12,#PlayerCompassY]                  ; =388

        MOV     R2,R3 ; end coords
        MOV     R3,R4
        MOV     R4,#Black
        BL      |DRAW2DLINE| ; draw compass needle

        LDR     R12,|PPLAYERINFO2|                 ; -> Word: &00019AA4
        LDR     R0,[R12,#PlayerFuelGaugeOrigX] ; load start coords
        LDR     R1,[R12,#PlayerFuelGaugeOrigY]                  ; =452
        SUB     R2,R0,#&0C ; end coords
        SUB     R3,R1,#&1C                      ; =28
        MOV     R4,#BrightRed                         ; =23
        BL      |DRAW2DLINE| ; draw fuel empty mark

        LDR     R12,|PPLAYERINFO2|                 ; -> Word: &00019AA4
        LDR     R0,[R12,#PlayerFuelGaugeOrigX] ; load start coords
        LDR     R1,[R12,#PlayerFuelGaugeOrigY]                  ; =452
        SUB     R2,R0,#&10 ; end coords
        SUB     R3,R1,#&1C                      ; =28
        MOV     R4,#BrightRed                         ; =23
        BL      |DRAW2DLINE| ; draw fuel empty mark

        LDR     R12,|PPLAYERINFO2|                 ; -> Word: &00019AA4
        LDR     R0,[R12,#AircraftFuel]                  ; =1<<6
        RSB     R0,R0,#&23,20                   ; =&23000
        MOV     R0,R0,ASR #3
        ADD     R0,R0,R0,ASR #1
        MOV     R0,R0,ASR #5
        BIC     R0,R0,#AngleStepMask
        ADD     R0,R0,#FuelAngle                  ; =&440
        ADD     R0,R0,#HalfTurn                   ; =&B40
|ANGLEMOD360LOOP3|
        CMP     R0,#FullRotation                      ; =&1680
        SUBGT   R0,R0,#FullRotation                   ; =&1680
        BGT     |ANGLEMOD360LOOP3|

        LDR     R1,|COSINE|                  ; -> Word: MemCosine
        LDR     R2,|SINE|                  ; -> Word: MemSine
        LDR     R3,[R1,R0]
        LDR     R4,[R2,R0]

        MVN     R3,R3,ASR #7
        MOV     R4,R4,ASR #7

        LDR     R0,[R12,#PlayerFuelGaugeOrigX] ; load start coords
        LDR     R1,[R12,#PlayerFuelGaugeOrigY]                  ; =452
        ADD     R3,R3,R0
        ADD     R4,R4,R1
        STR     R3,[R12,#PlayerFuelGaugeX] ; store end coords
        STR     R4,[R12,#PlayerFuelGaugeY]                  ; =404

        MOV     R2,R3 ; end coords
        MOV     R3,R4
        MOV     R4,#Black
        BL      |DRAW2DLINE| ; draw fuel needle

        LDR     R0,|MAXCOORDY6|                  ; -> Word: &00000000
        STR     R0,|MAXCOORDY4|                  ; -> Word: &00000000

        LDR     R14,|RETFROMDRAWGAUGES|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|RETFROMDRAWGAUGES|
        DCD     &00000000                       ; Word r/w (referenced)
        DCD     |AIRCRAFTTYPE|
|MAXCOORDY6|
        DCD     &00000000                       ; Word r/w (referenced)
        DCD     |L000016B0|
|L000016B0|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     |L000016C0|
|L000016C0|
        DCD     |L000016C8|
|DECKORGROUNDLEVEL|
        DCD     &00000000                       ;~ Word -/-
|L000016C8|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-

|UPDATEEXTERNALCAM|
        LDR     R9,|PPLAYERINFO2|                  ; -> Word: &00019AA4, Function entry, (alters flags)
        LDR     R9,[R9,#PlayerAircraftToViewPtr]                   ; =272
        LDR     R11,[R9,#AircraftViewAngle]                  ; =40

        LDR     R10,[R9,#AircraftHeading]
        MOV     R10,R10,ASR #AngleShift
        BIC     R10,R10,#AngleStepMask
        ADD     R11,R11,R10
        RSB     R11,R11,#FullRotation                 ; =&1680
        CMP     R11,#0
        ADDLT   R11,R11,#FullRotation                 ; =&1680

        ; Bug: R12 is never used
        LDR     R0,[R9,#AircraftViewQuarter]                   ; =36
        CMP     R0,#QuarterBack
        LDR     R12,[R9,#AircraftPitch]
        LDRGT   R12,[R9,#AircraftRoll]
        MOV     R12,R12,ASR #AngleShift
        BIC     R12,R12,#AngleStepMask
        RSBEQ   R12,R12,#FullRotation                 ; =&1680

        CMP     R0,#QuarterRight
        LDREQ   R12,[R9,#AircraftRoll]
        MOVEQ   R12,R12,ASR #AngleShift
        BICEQ   R12,R12,#AngleStepMask
        RSBEQ   R12,R12,#FullRotation                 ; =&1680

        ADD     R12,R12,#&19,28                 ; =&190
        CMP     R12,#0
        ADDLT   R12,R12,#FullRotation                 ; =&1680
        ; Bug: R12 is never used

        LDR     R0,|COSINE|                  ; -> Word: MemCosine
        LDR     R1,|SINE|                  ; -> Word: MemSine
        LDR     R2,[R1,R11]
        LDR     R3,[R0,R11]
        MOV     R2,R2,LSL #6
        ADD     R2,R2,R2,ASR #1
        MOV     R3,R3,LSL #6
        ADD     R3,R3,R3,ASR #1

        LDR     R4,|PSPLITSCREEN3|                  ; -> Word: &00016B28
        LDR     R4,[R4,#0]
        CMP     R4,#1
        MOVNE   R4,#&32000                      ; =&32000
        MOVEQ   R4,#&32,22                      ; =&C800

        LDR     R10,|PPLAYERINFO2|                 ; -> Word: &00019AA4
        LDR     R12,[R10,#PlayerAircraftToViewPtr]                 ; =272
        LDR     R11,[R12,#AircraftDamage]                 ; =56
        CMP     R11,#FatalAircraftDamage                        ; =11
        MOVGE   R2,R2,LSL #2
        MOVGE   R3,R3,LSL #2
        MOVGE   R11,#0
        STRGE   R11,[R10,#PlayerCamDistLog2]                 ; =276

        LDR     R12,|PPLAYERINFO2|                 ; -> Word: &00019AA4
        LDR     R12,[R12,#PlayerAircraftToViewPtr]                 ; =272
        LDR     R12,[R12,#AircraftType]                 ; =140

        CMP     R12,#ATYPE_FOKKER_V7_TWIN
        CMPNE   R12,#ATYPE_GOTHA_G_IV_BOMBER
        CMPNE   R12,#ATYPE_CARGO_AIRCRAFT
        MOVEQ   R2,R2,LSL #1
        MOVEQ   R3,R3,LSL #1
        MOVEQ   R4,R4,LSL #1

        CMP     R12,#ATYPE_GOTHA_G_IV_BOMBER
        CMPNE   R12,#ATYPE_CARGO_AIRCRAFT
        ADDEQ   R2,R2,R2,ASR #1
        ADDEQ   R3,R3,R3,ASR #1
        ADDEQ   R4,R4,R4,ASR #1

        LDR     R0,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDR     R0,[R0,#PlayerCamDistLog2]                   ; =276
        MOV     R2,R2,LSL R0
        MOV     R3,R3,LSL R0
        MOV     R4,R4,LSL R0

        LDR     R0,|PAIRCRAFTTOCAMERAVEC2|                  ; -> Word: &00018B88
        STMIA   R0,{R2-R4}

        MOV     PC,R14                          ; Function exit, Ends

|PSPLITSCREEN3|
        DCD     |SPLITSCREEN|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     |PLAYERNUM|
        DCD     &00011B60

|DRAWAIRCRAFTVIEWFORPLAYER1|
        ; bug: pointless (duplicates check below)
        LDR     R0,|PPLAYERINFO2|                  ; -> Word: &00019AA4, Function entry, (alters flags)
        LDR     R2,[R0,#AircraftDamage]                   ; =56
        CMP     R2,#FatalAircraftDamage                         ; =11
        MOVGT   PC,R14                          ; Function exit if GT

        LDR     R10,|PPLAYERINFO2|                 ; -> Word: &00019AA4

|DRAWAIRCRAFTVIEWFORPLAYER|
        ; r10 = player info
        LDR     R11,[R10,#AircraftDamage]                 ; =56, Function entry
        CMP     R11,#FatalAircraftDamage                        ; =11
        MOVGT   PC,R14                          ; Function exit if GT

        ADD     R11,R10,#AircraftCoord                    ; =20
        LDMIA   R11,{R2-R4}
        LDR     R0,|PAIRCRAFTCOORDS|                  ; -> Word: &00012A98
        STMIA   R0,{R2-R4} ; store aircraft coords

        LDR     R1,[R10,#AircraftHeading]
        MOV     R1,R1,ASR #AngleShift
        BIC     R1,R1,#AngleStepMask
        STR     R1,|HEADING|                  ; -> Word: &00000000

        LDR     R1,[R10,#AircraftPitch]
        MOV     R1,R1,ASR #AngleShift
        BIC     R1,R1,#AngleStepMask
        STR     R1,|PITCH|                  ; -> Word: &00000000

        LDR     R1,[R10,#AircraftRoll]
        MOV     R1,R1,ASR #AngleShift
        BIC     R1,R1,#AngleStepMask
        STR     R1,|ROLL|                  ; -> Word: &00000000

        MOV     R12,#ATYPE_PLAYER
|DRAWAIRCRAFT|
        ; R12 = Object number
        CMP     R12,#ATYPE_CAMERA                          ; Function entry
        MOVEQ   PC,R14                          ; Function exit if EQ
        STR     R14,|RETFROMDRAWAIRCRAFT|                 ; -> Word: &00000000

        LDR     R0,|HEADING|                  ; -> Word: &00000000
        LDR     R1,|PITCH|                  ; -> Word: &00000000
        LDR     R2,|ROLL|                  ; -> Word: &00000000

        LDR     R3,|PAIRCRAFTCOORDS|                  ; -> Word: &00012A98
        LDMIA   R3,{R3-R5} ; get coordinates of aircraft to draw

        LDR     R6,|PPLAYERINFO2|                  ; -> Word: &00019AA4
        LDR     R6,[R6,#PlayerAircraftToViewPtr]                   ; =272
        ADD     R6,R6,#AircraftCoord                      ; =20
        LDMIA   R6,{R7-R9} ; get coordinates of aircraft being viewed

        ; Don't draw the aircraft if too far away
        XABSDIFF R7,R7,R3
        CMP     R7,#&05,10                      ; =&1400000
        MOVGT   PC,R14                          ; Function exit if GT

        XABSDIFF R8,R8,R4
        CMP     R8,#&05,10                      ; =&1400000
        MOVGT   PC,R14                          ; Function exit if GT

        XABSDIFF R9,R9,R5
        CMP     R9,#&05,10                      ; =&1400000
        MOVGT   PC,R14                          ; Function exit if GT

        ; Don't draw the aircraft if too near (inside it)
        LDR     R6,[R6,#AircraftViewIn - AircraftCoord]
        CMP     R6,#ViewInside
        CMPEQ   R7,#0
        CMPEQ   R8,#0
        CMPEQ   R9,#0
        MOVEQ   PC,R14                          ; Function exit if EQ

        ; Coordinates of aircraft to draw
        MVN     R3,R3,ASR #AngleShift ; /(-1024)
        MVN     R4,R4,ASR #AngleShift
        MVN     R5,R5,ASR #AngleShift

        ; Angles of rotation of aircraft to draw
        RSB     R0,R0,#FullRotation                   ; =&1680
        RSB     R1,R1,#FullRotation                   ; =&1680
        RSB     R2,R2,#FullRotation                   ; =&1680

        BL      |DRAWAIRCRAFTWITHSHADOW|

        LDR     R14,|RETFROMDRAWAIRCRAFT|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|RETFROMDRAWAIRCRAFT|
        DCD     &00000000                       ; Word r/w (referenced)
        DCD     |PPLAYERINFO2|
|PPLAYERINFO3|
        DCD     |PLAYER1INFO|
        DCD     &00000002                       ;~~ Word -/-
        DCD     |L00001918|
|L00001918|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
|PAIRCRAFTCOORDS|
        DCD     |AIRCRAFTCOORDS|
        DCD     &00000000                       ;~ Word -/-
|AIRCRAFTCOORDS|
        DCD     &0CAA3000                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00009C00                       ;~~ Word -/-
|HEADING|
        DCD     &00000000                       ; Word r/w (referenced)
|PITCH|
        DCD     &00000000                       ; Word r/w (referenced)
|ROLL|
        DCD     &00000000                       ; Word r/w (referenced)
        DCD     |L00001944|
|L00001944|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     |L00001964|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
|L00001964|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-

|SERVICEALLAIRCRAFTWRAP|
        STR     R14,|RETFROMSERVICEALLAIRCRAFTWRAP|                 ; -> Word: &00000000, Function entry, (alters flags)
        MOV     R0,#0
        STR     R0,|AIRCRAFTPTRARRAYOFFSET|                  ; -> Word: &00000000
        BL      |SERVICEALLAIRCRAFT|
        LDR     R14,|RETFROMSERVICEALLAIRCRAFTWRAP|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|SERVICEAIRCRAFT|
        ; r0 = pointer to aircraft
        ADD     R3,R0,#AircraftCtrlX              ; ="" (144), Function entry, (alters flags)
        LDMIA   R3,{R4-R7}

        ADD     R3,R0,#AircraftCoord                      ; =20
        LDMIA   R3,{R8,R9}

        SUB     R8,R8,R4
        SUB     R9,R9,R5

        XABS    R8
        XABS    R9

        CMP     R8,R6,LSL #1 ; bug?
        CMP     R9,R7,LSL #1

        STR     R14,|RETFROMSERVICEAIRCRAFT|                 ; -> Word: &00000000
        ADD     R3,R0,#AircraftMsgRemain                      ; ="" (176)
        LDMIA   R3,{R1,R2}

        STR     R0,|PAIRCRAFT|                  ; -> Word: &00000000
        STR     R1,|MSGREMAIN|                  ; -> Word: &0000000A
        STR     R2,|MSGNUM|                  ; -> Word: &FFFFFFF6

        LDR     R0,|PAIRCRAFT|                  ; -> Word: &00000000
        LDR     R12,[R0,#AircraftType]                  ; =140
        CMP     R12,#ATYPE_CAMERA
        BNE     |NOTACAMERAPLANE|

        BL      |SERVICECAMERAPLANE|
        B       |DONECAMERAPLANE|                     ; Ends

|NOTACAMERAPLANE|
        LDR     R3,[R0,#AircraftDamage]                   ; =56
        CMP     R3,#CrashDamage2                         ; =15
        BGT     |AIRCRAFTISCRASHING|

        LDR     R1,|MSGREMAIN|                  ; -> Word: &0000000A
        LDR     R2,|MSGNUM|                  ; -> Word: &FFFFFFF6
        BL      |SERVICENORMALAIRCRAFT|

|DONECAMERAPLANE|
        LDR     R0,|PAIRCRAFT|                  ; -> Word: &00000000
        ADD     R0,R0,#AircraftCoord                      ; =20
        LDMIA   R0,{R1-R3}

        LDR     R10,[R0,#AircraftTargetPtr-AircraftCoord]   ; =152
        ADD     R10,R10,#AircraftCoord                    ; =20
        LDMIA   R10,{R10-R12}

        XABSDIFF R10,R10,R1
        XABSDIFF R11,R11,R2
        XABSDIFF R12,R12,R3

        CMP     R10,#&05,10                     ; =&1400000
        BGT     |NOADDAIRCRAFTTOARRAY|

        CMP     R11,#&05,10                     ; =&1400000
        BGT     |NOADDAIRCRAFTTOARRAY|

        CMP     R12,#&05,10                     ; =&1400000
        BGT     |NOADDAIRCRAFTTOARRAY|

        LDR     R0,|PAIRCRAFT|                  ; -> Word: &00000000
        LDR     R11,[R0,#AircraftDamage]                  ; =56
        CMP     R11,#FatalAircraftDamage                        ; =11
        BGT     |NOADDAIRCRAFTTOARRAY|

        LDR     R11,[R0,#AircraftType]                  ; =140
        CMP     R11,#ATYPE_CAMERA
        BEQ     |NOADDAIRCRAFTTOARRAY|

        LDR     R9,|AIRCRAFTPTRARRAY|                  ; -> Word: MemAircraftPointerArray
        LDR     R8,|AIRCRAFTPTRARRAYOFFSET|                  ; -> Word: &00000000
        ADD     R9,R8,R9
        STR     R0,[R9,#0]
        ADD     R8,R8,#BytesPerAddress
        STR     R8,|AIRCRAFTPTRARRAYOFFSET|                  ; -> Word: &00000000

|NOADDAIRCRAFTTOARRAY|
        LDR     R0,|PAIRCRAFT|                  ; -> Word: &00000000
        LDR     R12,[R0,#AircraftType]                  ; =140
        CMP     R12,#ATYPE_CAMERA
        BLNE    |UPDATEAIRCRAFTCOORDS|

        LDR     R0,|PAIRCRAFT|                  ; -> Word: &00000000
        LDR     R3,[R0,#AircraftTargetPtr]                   ; =172
        ADD     R3,R3,#AircraftCoord                      ; =20
        LDMIA   R3,{R0-R2} ; get target coordinates

        ADD     R3,R3,#(AircraftCoordCopy-AircraftCoord)   ; ="" (136)
        LDMIA   R3,{R3-R5} ; get previous target coordinates

        SUB     R5,R5,R2 ; calc target vector
        SUB     R4,R4,R1
        SUB     R3,R3,R0

        LDR     R0,|PAIRCRAFT|                  ; -> Word: &00000000
        LDR     R1,|MSGREMAIN|                  ; -> Word: &0000000A
        LDR     R2,|MSGNUM|                  ; -> Word: &FFFFFFF6
        BL      |FOLLOWTARGET|

        STR     R1,|MSGREMAIN|                  ; -> Word: &0000000A
        STR     R2,|MSGNUM|                  ; -> Word: &FFFFFFF6

        LDR     R0,|PAIRCRAFT|                  ; -> Word: &00000000
        LDR     R1,[R0,#AircraftDamage]                   ; =56
        CMP     R1,#(FatalAircraftDamage-1)                      ; =10
        LDRGT   R14,|RETFROMSERVICEAIRCRAFT|                 ; -> Word: &00000000
        MOVGT   PC,R14                          ; Function exit if GT

        LDR     R4,[R0,#AircraftType]                   ; =140
        CMP     R4,#ATYPE_CAMERA
        BLEQ    |L00001B44|

        LDR     R1,[R0,#AircraftFireGun]                   ; =32
        CMP     R1,#1
        MOVEQ   R1,#0
        STREQ   R1,[R0,#AircraftFireGun]                   ; =32

        LDMEQIA R0,{R7-R9}
        MOVEQ   R7,R7,ASR #AngleShift
        MOVEQ   R8,R8,ASR #AngleShift
        BICEQ   R7,R7,#AngleStepMask
        BICEQ   R8,R8,#AngleStepMask

        ADDEQ   R0,R0,#AircraftCoord                      ; =20
        LDMEQIA R0,{R4-R6}
        BLEQ    |ADDFLAK|

|L00001B1C|
        LDR     R1,|MSGREMAIN|                  ; -> Word: &0000000A
        LDR     R2,|MSGNUM|                  ; -> Word: &FFFFFFF6

        LDR     R0,|PAIRCRAFT|                  ; -> Word: &00000000
        ADD     R5,R0,#AircraftMsgRemain                      ; ="" (176)
        STMIA   R5,{R1,R2}

        LDR     R1,[R0,#AircraftType]                   ; =140
        CMP     R1,#ATYPE_GOTHA_G_IV_BOMBER
        BLEQ    |GOTHA|

        LDR     R14,|RETFROMSERVICEAIRCRAFT|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|L00001B44|
        LDR     R4,|P2COUNT0TO2|                  ; -> Word: &00011FB8, Function entry, (alters flags)
        LDR     R4,[R4,#0]
        CMP     R4,#1
        BNE     |L00001B1C|
        MOV     PC,R14                          ; Function exit, Ends

|PAIRCRAFT|
        DCD     &00000000                       ; Word r/w (referenced)
|AIRCRAFTDATAARRAY2|
        DCD     MemAircraftDataArray                       ; Word r/- (referenced)
|AIRCRAFTNUM|
        DCD     &00000000                       ; Word r/w (referenced)
|MSGREMAIN|
        DCD     &0000000A                       ; Word r/w (referenced)
|MSGNUM|
        DCD     &FFFFFFF6                       ; Word r/w (referenced)
|P2COUNT0TO2|
        DCD     |COUNT0TO2|
|RETFROMSERVICEAIRCRAFT|
        DCD     &00000000                       ; Word r/w (referenced)
|RETFROMSERVICEALLAIRCRAFTWRAP|
        DCD     &00000000                       ; Word r/w (referenced)
|PPLAYER1COORDS|
        DCD     |PLAYER1COORDS|
|PPLAYER2COORDS|
        DCD     |PLAYER2COORDS|

|COPYPLAYERCOORDS|
        LDR     R0,|PPLAYER1COORDS|                  ; -> Word: &00019AB8, Function entry, (alters flags)
        LDMIA   R0,{R1-R3}
        ADD     R0,R0,#(AircraftCoordCopy-AircraftCoord) ; ="" (136)
        STMIA   R0,{R1-R3}

        LDR     R0,|PPLAYER2COORDS|                  ; -> Word: &00019CC4
        LDMIA   R0,{R1-R3}
        ADD     R0,R0,#(AircraftCoordCopy-AircraftCoord)  ; ="" (136)
        STMIA   R0,{R1-R3}

        MOV     PC,R14                          ; Function exit, Ends

|DRAWALLAIRCRAFT|
        STR     R14,|RETFROMSERVICEAIRCRAFT|                 ; -> Word: &00000000, Function entry, (alters flags)
        LDR     R0,|AIRCRAFTDATAARRAY2|                  ; -> Word: MemAircraftDataArray
        STR     R0,|PAIRCRAFT|                  ; -> Word: &00000000

        MOV     R0,#(NumPracticeAircraft-1)                         ; =19
        STR     R0,|AIRCRAFTNUM|                  ; -> Word: &00000000

|DRAWAIRCRAFTLOOP|
        LDR     R0,|PAIRCRAFT|                  ; -> Word: &00000000
        LDR     R7,[R0,#AircraftDamage]                   ; =56
        CMP     R7,#FatalAircraftDamage                         ; =11
        BGT     |DRAWNEXTAIRCRAFT|

        LDMIA   R0,{R7-R9} ; get angles
        ADD     R0,R0,#AircraftCoord                      ; =20
        LDMIA   R0,{R1-R3} ; get coordinates

        MOV     R4,R8,ASR #AngleShift
        MOV     R5,R7,ASR #AngleShift
        MOV     R6,R9,ASR #AngleShift

        BIC     R4,R4,#AngleStepMask
        BIC     R5,R5,#AngleStepMask
        BIC     R6,R6,#AngleStepMask

        LDR     R0,|PAIRCRAFTCOORDS|                  ; -> Word: &00012A98
        STMIA   R0,{R1-R6}

        LDR     R0,|PAIRCRAFT|                  ; -> Word: &00000000
        LDR     R12,[R0,#AircraftType]                  ; =140
        BL      |DRAWAIRCRAFT|

|DRAWNEXTAIRCRAFT|
        LDR     R0,|PAIRCRAFT|                  ; -> Word: &00000000
        ADD     R0,R0,#BytesPerAircraft                      ; ="" (184)
        STR     R0,|PAIRCRAFT|                  ; -> Word: &00000000

        LDR     R0,|AIRCRAFTNUM|                  ; -> Word: &00000000
        SUBS    R0,R0,#1
        STR     R0,|AIRCRAFTNUM|                  ; -> Word: &00000000
        BPL     |DRAWAIRCRAFTLOOP|

        LDR     R14,|RETFROMSERVICEAIRCRAFT|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|AIRCRAFTPTRARRAYOFFSET|
        DCD     &00000000                       ; Word r/w (referenced)
|AIRCRAFTPTRARRAY|
        DCD     MemAircraftPointerArray                       ; Word r/- (referenced)
|PLAYERBULLETSARRAY|
        DCD     MemPlayerBulletsArray                       ; Word r/- (referenced)
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
|SMOKEORBULLETCOUNT|
        DCD     &00000000                       ; Word r/w (referenced)
|RETFROMSERVICEPLAYERBULLETS|
        DCD     &00000000                       ; Word r/w (referenced)
|UNKNOWNBOOLADDR|
        DCD     |L000059BC|

|SERVICEPLAYERBULLETS|
        LDR     R0,|PLAYERBULLETSARRAY|                  ; -> Word: MemPlayerBulletsArray, Function entry, (alters flags)
        STR     R14,|RETFROMSERVICEPLAYERBULLETS|                 ; -> Word: &00000000
        MOV     R2,#0
        STR     R2,|SMOKEORBULLETCOUNT|                  ; -> Word: &00000000
|SERVICEPLAYERBULLETLOOP|
        LDMIA   R0,{R2-R8}
        LDR     R9,|UNKNOWNBOOLADDR|                  ; -> Word: &00016B2C
        LDR     R9,[R9,#0]
        CMP     R9,#0
        BNE     |UPDATEBULLETSTATE|

        CMP     R8,#0
        CMPNE   R8,#&64                         ; ="d" (100)
        SUBNE   R2,R2,R5 ; add vector to bullet position
        SUBNE   R3,R3,R6
        SUBNE   R4,R4,R7
        BEQ     |BULLETISDEAD|

        SUB     R8,R8,#1
        CMP     R4,#0 ; check for collision with the ground
        BLT     |BULLETHITGROUND| ; bullet is underground

        LDR     R14,|NUMSTATICOBJECTSMINUS1|                 ; -> Word: &00000000
        CMP     R14,#0
        BGE     |CHECKBULLETHITSTATIC|

        B       |CHECKBULLETHITDYNAMIC|                     ; Ends

|CHECKBULLETHITSTATIC|
        STMFD   R13!,{R0-R12}
        LDR     R0,|BULLETINFOFORMAP|                  ; -> Word: &0002DC50
|CHECKHITSTATICOBJECTLOOP|
        LDMIA   R0!,{R5-R10}

        ; Compute absolute vector between static collision box and bullet
        XABSDIFF R5,R5,R2
        XABSDIFF R6,R6,R3
        XABSDIFF R7,R7,R4

        ; Check absolute vector of the bullet against the static collision box
        CMP     R5,R8
        BGT     |CHECKNEXTSTATICOBJECT|

        CMP     R6,R9
        BGT     |CHECKNEXTSTATICOBJECT|

        CMP     R7,R10
        BGT     |CHECKNEXTSTATICOBJECT|

        LDMFD   R13!,{R0-R12}
        B       |BULLETHITGROUND|                     ; Ends

|CHECKNEXTSTATICOBJECT|
        SUBS    R14,R14,#1
        BPL     |CHECKHITSTATICOBJECTLOOP|
        LDMFD   R13!,{R0-R12}
        B       |CHECKBULLETHITDYNAMIC|                     ; Ends

|NUMSTATICOBJECTSMINUS1|
        DCD     &00000000                       ; Word r/- (referenced)
|BULLETINFOFORMAP|
        DCD     &0002DC50                       ; Word r/- (referenced)

|BULLETHITGROUND|
        MOV     R5,#SmokeTypeQuickFire
        BL      |ADDSMOKEGEN|
        B       |BULLETISDEAD|                     ; Ends

|L00001D04|
        DCD     &00000000                       ;~ Word -/-

|CHECKBULLETHITDYNAMIC|
        STMFD   R13!,{R0-R12}
        LDR     R11,|AIRCRAFTPTRARRAY|                 ; -> Word: MemAircraftPointerArray
|L00001D10|
        LDR     R1,|AIRCRAFTPTRARRAYOFFSET|                  ; -> Word: &00000000
        CMP     R8,#&64                         ; ="d" (100)
        LDRGE   R8,|PLAYER1INFOB|                  ; -> Word: &00019AA4
        LDRLT   R8,|PPLAYER2INFO5|                  ; -> Word: &00019CB0

        LDR     R0,[R8,#AircraftDamage]                   ; =56
        CMP     R0,#FatalAircraftDamage                         ; =11
        STRLE   R8,[R11,R1]
        ADDLE   R1,R1,#BytesPerAddress
        CMP     R1,#0
        LDMEQFD R13!,{R0-R12}
        BEQ     |NOAIRCRAFTTOCHECK|

|CHECKAIRCRAFTHITLOOP|
        LDR     R0,[R11,#0] ; get aircraft data address
        LDR     R9,[R0,#AircraftType]                   ; =140
        CMP     R9,#ATYPE_GOTHA_G_IV_BOMBER
        CMPNE   R9,#ATYPE_CARGO_AIRCRAFT
        MOVEQ   R9,#BigAircraftBulletCollSizeXY                  ; =&96000
        MOVNE   R9,#SmallAircraftBulletCollSizeXY                ; =&25800
        ADD     R0,R0,#AircraftCoord                      ; =20
        LDMIA   R0,{R5-R7}

        ; Compute vector between aircraft and bullet
        SUB     R5,R5,R2
        SUB     R6,R6,R3
        SUB     R7,R7,R4

        ; Make distance absolute
        XABS    R5
        XABS    R6
        XABS    R7

        ; Check absolute distance of the bullet against the plane collision box
        CMP     R5,R9
        BGT     |CHECKNEXTAIRCRAFT|
        CMP     R6,R9
        BGT     |CHECKNEXTAIRCRAFT|
        CMP     R7,#AircraftBulletCollSizeZ              ; =&19000
        BGT     |CHECKNEXTAIRCRAFT|

        ; It's a hit
        LDR     R9,[R0,#(AircraftPitch-AircraftCoord)]                  ; =-20
        ADD     R9,R9,#HitPitchChange            ; =&C800
        STR     R9,[R0,#(AircraftPitch-AircraftCoord)]                  ; =-20

        LDR     R9,[R0,#(AircraftRoll-AircraftCoord)]                  ; =-12
        ADD     R9,R9,#HitRollChange          ; =&C800
        STR     R9,[R0,#(AircraftRoll-AircraftCoord)]                  ; =-12

        LDR     R9,[R0,#(AircraftDamage-AircraftCoord)]                   ; =36
        CMP     R9,#FatalAircraftDamage                         ; =11
        BGE     |ALREADYMAXDAMAGE|

        LDR     R9,[R0,#(AircraftDamage-AircraftCoord)]                   ; =36
        ADD     R9,R9,#1
        STR     R9,[R0,#(AircraftDamage-AircraftCoord)]                   ; =36

        MOV     R7,R0
        MOV     R8,R1
        MOV     R9,R2
        MOV     R10,R3
        MOV     R0,#ChannelMisc
        MOV     R1,#VoiceExplodeMD3
        SWI     Sound_AttachVoice

        MOV     R0,#ChannelMisc
        MVN     R1,#9
        MOV     R2,#BulletHitAircraftPitch        ; =&1600
        MOV     R3,#0
        SWI     Sound_Control

        MOV     R0,R7
        MOV     R1,R8
        MOV     R2,R9
        MOV     R3,R10

        LDR     R12,|PTMPSTORE2|                 ; -> Word: &0001898C
        LDMIA   R12,{R0-R11}

|ALREADYMAXDAMAGE|
        MOV     R5,#SmokeTypeQuickFire
        MOV     R10,R11
        BL      |ADDSMOKEGEN|
        MOV     R11,R10

        LDR     R12,|PTMPSTORE2|                 ; -> Word: &0001898C
        LDMIA   R12,{R0-R11}

        LDMFD   R13!,{R0-R12}
        B       |BULLETISDEAD|                     ; Ends

|CHECKNEXTAIRCRAFT|
        ADD     R11,R11,#BytesPerAddress
        SUB     R1,R1,#4
        CMP     R1,#0
        BGT     |CHECKAIRCRAFTHITLOOP|
        LDMFD   R13!,{R0-R12}
|NOAIRCRAFTTOCHECK|
        LDR     R12,|PTMPSTORE2|                 ; -> Word: &0001898C
        STMIA   R12,{R0-R11}

        LDR     R11,|TARGETPTRARRAY|                 ; -> Word: MemTargetPointerArray
        LDR     R1,|TARGETARRAYWRITEOFFSET|                  ; -> Word: &00000000
        CMP     R1,#0
        BEQ     |UPDATEBULLETSTATE|
|CHECKTARGETHITLOOP|
        LDR     R0,[R11,#0] ; get target address
        LDMIA   R0,{R5-R10}

        ; Compute vector between target and bullet
        ADD     R5,R2,R5,LSL #10
        ADD     R6,R3,R6,LSL #10
        ADD     R7,R4,R7,LSL #10

        ; Make distance absolute
        XABS    R5
        XABS    R6
        XABS    R7

        ; Check absolute distance of the bullet against the collision box
        CMP     R5,R8
        BGT     |PLAYERBULLETMISSEDTARGET|

        CMP     R6,R9
        BGT     |PLAYERBULLETMISSEDTARGET|

        CMP     R7,R10
        BGT     |PLAYERBULLETMISSEDTARGET|

        ; It's a hit
        MOV     R10,R11
        MOV     R5,#SmokeTypeQuickFire
        BL      |ADDSMOKEGEN|
        MOV     R11,R10

        LDR     R10,[R0,#TargetHitpoints]                  ; =28
        SUB     R10,R10,#1
        STR     R10,[R0,#TargetHitpoints]                  ; =28

        MOV     R5,R0
        MOV     R6,R1
        MOV     R7,R2
        MOV     R8,R3

        MOV     R0,#ChannelMisc
        MOV     R1,#VoiceExplodeMD3
        SWI     Sound_AttachVoice

        MOV     R0,#ChannelMisc
        MVN     R1,#9
        MOV     R2,#BulletHitGroundTargetPitch   ; =&1600
        MOV     R3,#0
        SWI     Sound_Control

        MOV     R0,R5
        MOV     R1,R6
        MOV     R2,R7
        MOV     R3,R8

        CMP     R10,#0
        LDRGT   R10,|PPLAYERINFO15|                 ; -> Word: &00000000
        LDRGT   R9,[R10,#AircraftScore]                  ; =60
        ADDGT   R9,R9,#ScorePerBulletOnTarget
        STRGT   R9,[R10,#AircraftScore]                  ; =60

        LDR     R12,|PTMPSTORE2|                 ; -> Word: &0001898C
        LDMIA   R12,{R0-R11}
        B       |BULLETISDEAD|                     ; Ends

|PLAYERBULLETMISSEDTARGET|
        ADD     R11,R11,#BytesPerAddress
        SUB     R1,R1,#4
        CMP     R1,#0
        BGT     |CHECKTARGETHITLOOP|

        LDR     R12,|PTMPSTORE2|                 ; -> Word: &0001898C
        LDMIA   R12,{R0-R11}
        B       |UPDATEBULLETSTATE|                     ; Ends

|TARGETPTRARRAY|
        DCD     MemTargetPointerArray                       ; Word r/- (referenced)
|PTMPSTORE2|
        DCD     |TMP|

|UPDATEBULLETSTATE|
        STMIA   R0,{R2-R8}
        CMP     R8,#0
        CMPNE   R8,#&64                         ; ="d" (100)
        BEQ     |NEXTPLAYERBULLET|

        LDR     R1,|PPLAYERINFO15|                  ; -> Word: &00000000
        LDR     R1,[R1,#AircraftViewMap]                   ; =168
        CMP     R1,#0
        BNE     |NEXTPLAYERBULLET|

        LDR     R1,|PCAMERA|                  ; -> Word: &00011B3C
        ADD     R1,R1,#CameraPos                      ; =12
        LDMIA   R1,{R5-R7}

        SUB     R2,R5,R2 ; Make bullet coords relative to camera
        SUB     R3,R6,R3
        SUB     R4,R7,R4

        MOV     R2,R2,ASR #AngleShift
        MOV     R3,R3,ASR #AngleShift
        MOV     R4,R4,ASR #AngleShift

        LDR     R14,|PCAMERA|                 ; -> Word: &00011B3C
        LDR     R11,[R14,#CameraAngleX]
        MOV     R6,R2
        MOV     R7,R3
        BL      |ROTATE| ; coords R6,R7 (updated), angle R11

        MOV     R2,R6
        MOV     R3,R7
        LDR     R14,|PCAMERA|                 ; -> Word: &00011B3C
        LDR     R11,[R14,#CameraAngleY]
        MOV     R6,R3
        MOV     R7,R4
        BL      |ROTATE| ; coords R6,R7 (updated), angle R11

        MOV     R3,R6
        MOV     R4,R7
        LDR     R14,|PCAMERA|                 ; -> Word: &00011B3C
        LDR     R11,[R14,#CameraAngleZ]
        MOV     R6,R2
        MOV     R7,R4
        BL      |ROTATE| ; coords R6,R7 (updated), angle R11

        MOV     R11,R6
        MOV     R12,R7
        ADD     R3,R3,#5
        CMP     R3,#5
        BLT     |NEXTPLAYERBULLET|

        STR     R3,|L000021C8|                  ; -> Word: &00000000

        CMP     R3,#&C8                         ; ="" (200)
        LDRLT   R8,|BULLETDIVIDENDA|                  ; -> Word: &0000927C
        LDRGE   R8,|L000021BC|                  ; -> Word: &000249F0
        MOVLT   R9,#6
        MOVGE   R9,#8

        CMP     R3,#&01,22                      ; =&400
        LDRGE   R8,|L000021C0|                  ; -> Word: &00124F80
        MOVGE   R9,#&0B                         ; =11

        CMP     R3,#&0A,22                      ; =&2800
        LDRGE   R8,|L000021C4|                  ; -> Word: &00927C00
        MOVGE   R9,#&0E                         ; =14

        MOV     R1,R3
        BL      |DIVIDE| ; returns quotient in R3
        ADD     R12,R12,#&28                    ; ="(" (40)

        MUL     R2,R11,R3
        MOV     R2,R2,ASR R9

        MUL     R4,R12,R3
        MOV     R4,R4,ASR R9

        LDR     R11,|SCREENLIMITSPTR4|                 ; -> Word: &0001142C
        LDMIA   R11,{R11,R12}

        ADD     R2,R2,R11,LSL #(CoordToScreenLog2-1)
        MOV     R2,R2,ASR #CoordToScreenLog2

        ADD     R4,R4,R12,LSL #(CoordToScreenLog2-1)
        MOV     R4,R4,ASR #CoordToScreenLog2

        ; Check whether the bullet is on-screen or not
        SUB     R12,R12,#2

        CMP     R2,#1
        BLT     |NEXTPLAYERBULLET|

        CMP     R4,#1
        BLT     |NEXTPLAYERBULLET|

        CMP     R2,R11
        BGT     |NEXTPLAYERBULLET|

        CMP     R4,R12
        BGT     |NEXTPLAYERBULLET|

        ; Draw the player's bullet
        LDR     R11,|FRAMEBUFFER2|                 ; -> Word: &00000000
        MOV     R12,#RowStride                     ; =&140
        MUL     R10,R4,R12
        ADD     R11,R11,R10
        ADD     R11,R11,R2
        MOV     R9,#OffYellow                         ; ="v" (118)
        LDR     R3,|L000021C8|                  ; -> Word: &00000000
        CMP     R3,#&05,18                      ; =&14000
        BGT     |NEXTPLAYERBULLET|

        STRB    R9,[R11,#0]
        CMP     R3,#&02,22                      ; =&800
        STRLTB  R9,[R11,#1]
        STRLTB  R9,[R11,#RowStride]                  ; =5<<6
        STRLTB  R9,[R11,#(RowStride+1)]                  ; =321

|NEXTPLAYERBULLET|
        ADD     R0,R0,#BytesPerPlayerBullet                      ; =" " (32)
        LDR     R1,|SMOKEORBULLETCOUNT|                  ; -> Word: &00000000
        ADD     R1,R1,#1
        STR     R1,|SMOKEORBULLETCOUNT|                  ; -> Word: &00000000
        CMP     R1,#NumPlayerBullets                         ; ="" (141)
        BLT     |SERVICEPLAYERBULLETLOOP|
        LDR     R14,|RETFROMSERVICEPLAYERBULLETS|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|L000020C4|
        DCD     |L000020D0|
|PCAMERA|
        DCD     |CAMERA|
|SCREENLIMITSPTR4|
        DCD     |MAXCOORDX3|
|L000020D0|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     &00000000                       ;~ Word -/-
|PLAYER1INFOB|
        DCD     |PLAYER1INFO|
|PPLAYER2INFO5|
        DCD     |PLAYER2INFO|
|BULLETPITCH|
        DCD     &00000000                       ; Word -/w (referenced)
|BULLETYAW|
        DCD     &00000000                       ; Word -/w (referenced)

|BULLETISDEAD|
        MOV     R1,#0
        STR     R1,[R0,#&018]                   ; =24

        LDR     R1,|PLAYER1INFOB|                  ; -> Word: &00019AA4
        MOV     R14,#&46                        ; ="F" (70)

        LDR     R2,[R1,#AircraftFireGun]                   ; =32
        CMP     R2,#0
        LDREQ   R1,|PPLAYER2INFO5|                  ; -> Word: &00019CB0
        LDREQ   R2,[R1,#AircraftFireGun]                   ; =32
        MOVEQ   R14,#&AA                        ; ="" (170)
        CMPEQ   R2,#0
        BEQ     |NEXTPLAYERBULLET|

        MOV     R2,#0
        STR     R2,[R1,#AircraftFireGun]                   ; =32

        ADD     R2,R1,#AircraftCoord                      ; =20
        LDMIA   R2,{R2-R4}

        LDR     R5,|COSINE2|                  ; -> Word: MemCosine
        LDR     R6,|SINE2|                  ; -> Word: MemSine

        LDR     R7,[R1,#AircraftPitch]
        MOV     R7,R7,ASR #12
        MOV     R7,R7,LSL #2

        LDR     R8,[R1,#AircraftHeading]
        MOV     R8,R8,ASR #12
        MOV     R8,R8,LSL #2

        LDR     R9,|PLAYERBULLETSARRAY|                  ; -> Word: MemPlayerBulletsArray
        CMP     R9,R0 ; is it MemPlayerBulletsArray, i.e. bullet 0?
        STREQ   R7,|BULLETPITCH|                  ; -> Word: &00000000
        STREQ   R8,|BULLETYAW|                  ; -> Word: &00000000

        RSB     R8,R8,#FullRotation                   ; =&1680
        CMP     R8,#0
        ADDLT   R8,R8,#FullRotation                   ; =&1680
        LDR     R9,[R6,R8]
        LDR     R10,[R5,R8]
        LDR     R11,[R5,R7]
        LDR     R12,[R6,R7]
        MUL     R7,R9,R11
        MUL     R8,R10,R11
        MOV     R5,R7,ASR #6
        MOV     R6,R8,ASR #6
        MOV     R7,R12,LSL #6
        STMIA   R0,{R2-R7,R14}
        B       |NEXTPLAYERBULLET|                     ; Ends

|PAIRCRAFTPITCH|
        DCD     |AIRCRAFTPITCH|

|CLEARPLAYERBULLETSARRAY|
        LDR     R0,|PLAYERBULLETSARRAY|                  ; -> Word: MemPlayerBulletsArray, Function entry, (alters flags)
        MOV     R1,#&32                         ; ="2" (50)
        MOV     R2,#0
|CLEARBULLETSLOOP|
        STR     R2,[R0,#0]
        ADD     R0,R0,#4
        ADD     R1,R1,#1
        CMP     R1,#&4B,28                      ; =&4B0
        BLT     |CLEARBULLETSLOOP|
        MOV     PC,R14                          ; Function exit, Ends

|BULLETDIVIDENDA|
        DCD     &0000927C                       ; Word r/- (referenced)
|L000021BC|
        DCD     &000249F0                       ; Word r/- (referenced)
|L000021C0|
        DCD     &00124F80                       ; Word r/- (referenced)
|L000021C4|
        DCD     &00927C00                       ; Word r/- (referenced)
|L000021C8|
        DCD     &00000000                       ; Word r/w (referenced)
|PUFFARRAY|
        DCD     &0002A5E0                       ; Word r/- (referenced)
|SMOKEGENOFFSET|
        DCD     &00000000                       ; Word r/w (referenced)
        DCD     |STATICAIRCRAFTFIREGUN|
|PUFFCOUNT|
        DCD     &00000000                       ; Word r/w (referenced)
|MAKEPUFFSCOUNT|
        DCD     &00000000                       ; Word r/w (referenced)

|ADDSMOKEGEN|
        ; r2,r3,r4 = x,y,z
        ; r5 = smoke type (0,1,2)
        LDR     R12,|SMOKEGENOFFSET|                 ; -> Word: &00000000, Function entry, (alters flags)
        LDR     R11,|SMOKEGEN|                 ; -> Word: MemSmoke
        ADD     R11,R11,R12
        STMIA   R11,{R2-R5}
        ADD     R12,R12,#BytesPerSmokeGen                    ; =24
        CMP     R12,#&0F,26                     ; =&3C0
        SUBGT   R12,R12,#BytesPerSmokeGen                    ; =24
        STR     R12,|SMOKEGENOFFSET|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|SERVICESMOKE|
        LDR     R0,|PUFFARRAY|                  ; -> Word: &0002A5E0, Function entry, (alters flags)
        STR     R14,|RETFROMPUFFSORBULLETS|                 ; -> Word: &00000000
        MOV     R2,#0
        STR     R2,|SMOKEORBULLETCOUNT|                  ; -> Word: &00000000
|SERVICESMOKELOOP|
        LDR     R2,[R0,#0] ; check smoke's remaining time
        CMP     R2,#0
        BEQ     |SMOKEGONE|
        LDR     R8,|UNKNOWNBOOLADDR|                  ; -> Word: &00016B2C
        LDR     R8,[R8,#0]
        CMP     R8,#0
        SUBEQ   R2,R2,#1 ; reduce smoke's remaining time
        STREQ   R2,[R0,#0]
        LDR     R2,[R0,#4] ; get smoke type
        STR     R2,|SMOKETYPE|                  ; -> Word: &00000000
        ADD     R0,R0,#BytesPerSmokeHeader
        MOV     R1,#0
        STR     R1,|PUFFCOUNT|                  ; -> Word: &00000000
|SERVICEPUFFLOOP|
        LDMIA   R0,{R2-R7}
        LDR     R8,|UNKNOWNBOOLADDR|                  ; -> Word: &00016B2C
        LDR     R8,[R8,#0]
        CMP     R8,#0
        BNE     |NOMOVEPUFF|
        SUB     R2,R2,R5 ; add vector to puff position
        SUB     R3,R3,R6
        SUB     R4,R4,R7
        CMP     R4,#0
        MOVLT   R4,#0 ; puffs can't go underground
        MVNLT   R7,R7 ; bounce off the ground
        STMIA   R0,{R2-R7}
|NOMOVEPUFF|
        LDR     R1,|PPLAYERINFO15|                  ; -> Word: &00000000
        LDR     R1,[R1,#AircraftViewMap]                   ; =168
        CMP     R1,#0
        BNE     |NEXTPUFF|

        LDR     R1,|PCAMERA|                  ; -> Word: &00011B3C
        ADD     R1,R1,#CameraPos                      ; =12
        LDMIA   R1,{R5-R7}

        SUB     R2,R5,R2 ; Make smoke coords relative to camera
        SUB     R3,R6,R3
        SUB     R4,R7,R4

        MOV     R2,R2,ASR #AngleShift
        MOV     R3,R3,ASR #AngleShift
        MOV     R4,R4,ASR #AngleShift

        LDR     R14,|PCAMERA|                 ; -> Word: &00011B3C
        LDR     R11,[R14,#CameraAngleX]

        MOV     R6,R2
        MOV     R7,R3
        BL      |ROTATE| ; coords R6,R7 (updated), angle R11
        MOV     R2,R6
        MOV     R3,R7

        LDR     R14,|PCAMERA|                 ; -> Word: &00011B3C
        LDR     R11,[R14,#CameraAngleY]

        MOV     R6,R3
        MOV     R7,R4
        BL      |ROTATE| ; coords R6,R7 (updated), angle R11
        MOV     R3,R6
        MOV     R4,R7

        LDR     R14,|PCAMERA|                 ; -> Word: &00011B3C
        LDR     R11,[R14,#CameraAngleZ]

        MOV     R6,R2
        MOV     R7,R4
        BL      |ROTATE| ; coords R6,R7 (updated), angle R11
        MOV     R11,R6
        MOV     R12,R7

        ADD     R3,R3,#5
        CMP     R3,#5
        BLT     |NEXTPUFF|

        CMP     R3,#&C8                         ; ="" (200)
        LDRLT   R8,|BULLETDIVIDENDA|                  ; -> Word: &0000927C
        LDRGE   R8,|L000021BC|                  ; -> Word: &000249F0
        MOVLT   R9,#6
        MOVGE   R9,#8

        CMP     R3,#&01,22                      ; =&400
        LDRGE   R8,|L000021C0|                  ; -> Word: &00124F80
        MOVGE   R9,#&0B                         ; =11

        CMP     R3,#&0A,22                      ; =&2800
        LDRGE   R8,|L000021C4|                  ; -> Word: &00927C00
        MOVGE   R9,#&0E                         ; =14
        MOV     R1,R3
        STR     R1,|PUFFDIST|                  ; -> Word: &00000000
        BL      |DIVIDE| ; returns quotient in R3

        MUL     R2,R11,R3
        MOV     R2,R2,ASR R9
        MUL     R4,R12,R3
        MOV     R4,R4,ASR R9

        LDR     R11,|SCREENLIMITSPTR4|                 ; -> Word: &0001142C
        LDMIA   R11,{R11,R12}
        SUB     R12,R12,#2

        ADD     R2,R2,R11,LSL #(CoordToScreenLog2-1)
        SUB     R2,R2,#&0C                      ; =12
        MOV     R2,R2,ASR #CoordToScreenLog2

        ADD     R4,R4,R12,LSL #(CoordToScreenLog2-1)
        MOV     R4,R4,ASR #CoordToScreenLog2

        CMP     R2,#1
        BLT     |NEXTPUFF|

        CMP     R4,#5
        BLT     |NEXTPUFF|

        SUB     R11,R11,#8
        CMP     R2,R11
        BGT     |NEXTPUFF|

        CMP     R4,R12
        BGT     |NEXTPUFF|

        LDR     R11,|FRAMEBUFFER2|                 ; -> Word: &00000000
        MOV     R12,#RowStride                     ; =&140
        MUL     R10,R4,R12
        ADD     R11,R11,R10
        ADD     R11,R11,R2
        LDR     R9,|PUFFCOUNT|                  ; -> Word: &00000000
        CMP     R9,#1
        MOVLT   R9,#Peridot                         ; ="t" (116)
        MOVGE   R9,#BrickRed                         ; ="<" (60)
        LDR     R10,|SMOKETYPE|                 ; -> Word: &00000000
        CMP     R10,#SmokeTypeQuickFire
        BEQ     |FIREPUFF|

        CMP     R9,#Peridot                         ; ="t" (116)
        MOVEQ   R9,#DarkGrey              ; ="-" (45)
        MOVNE   R9,#Black

|FIREPUFF|
        LDR     R3,|PUFFDIST|                  ; -> Word: &00000000
        CMP     R3,#&01,20                      ; =&1000
        BGT     |NOBIGPUFF|

        STRB    R9,[R11,#4]
        STRB    R9,[R11,#-RowStride]                 ; =&3FFFFFB<<6
        STRB    R9,[R11,#-RowStride+2]                 ; =-318
        STRB    R9,[R11,#(-RowStride*3)+5]                ; =-955
        STRB    R9,[R11,#(-RowStride*4)+4]                 ; =-1276
        STRB    R9,[R11,#(-RowStride*5)+2]                 ; =-1598

|NOBIGPUFF|
        CMP     R3,#&0A,22                      ; =&2800
        BGT     |NOMEDIUMPUFF|

        STRB    R9,[R11,#(-RowStride*3)+3]                 ; =-957
        STRB    R9,[R11,#-RowStride+5]                 ; =-315

|NOMEDIUMPUFF|
        CMP     R3,#&05,20                      ; =&5000
        BGT     |NOSMALLPUFF|

        STRB    R9,[R11,#(-RowStride*2)+1]                 ; =-639

|NOSMALLPUFF|
        CMP     R3,#&0A,20                      ; =&A000
        BGT     |NEXTPUFF|

        STRB    R9,[R11,#(-RowStride*2)+4]                 ; =-636

|NEXTPUFF|
        ADD     R0,R0,#BytesPerPuff                      ; =24
        LDR     R1,|PUFFCOUNT|                  ; -> Word: &00000000
        ADD     R1,R1,#1
        STR     R1,|PUFFCOUNT|                  ; -> Word: &00000000
        CMP     R1,#NumPuffs-1
        BLE     |SERVICEPUFFLOOP|

|NEXTSMOKEGEN|
        LDR     R1,|SMOKEORBULLETCOUNT|                  ; -> Word: &00000000
        ADD     R1,R1,#1
        STR     R1,|SMOKEORBULLETCOUNT|                  ; -> Word: &00000000
        CMP     R1,#NumSmokeGen                         ; ="(" (40)
        BLT     |SERVICESMOKELOOP|

        MOV     R1,#0
        STR     R1,|SMOKEGENOFFSET|                  ; -> Word: &00000000
        LDR     R14,|RETFROMPUFFSORBULLETS|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|SMOKETYPE|
        DCD     &00000000                       ; Word r/w (referenced)
|PUFFDIST|
        DCD     &00000000                       ; Word r/w (referenced)

|SMOKEGONE|
        LDR     R1,|SMOKEGENOFFSET|                  ; -> Word: &00000000
        CMP     R1,#0
        ADDEQ   R0,R0,#BytesPerSmoke                 ; ="P" (80)
        BEQ     |NEXTSMOKEGEN|
        SUB     R1,R1,#BytesPerSmokeGen                      ; =24
        STR     R1,|SMOKEGENOFFSET|                  ; -> Word: &00000000
        MOV     R1,#0
        STR     R1,|MAKEPUFFSCOUNT|                  ; -> Word: &00000000
        MOV     R1,#QuickSmokeFrames                         ; =10
        STR     R1,[R0,#0]
        LDR     R1,|SMOKEGENOFFSET|                  ; -> Word: &00000000
        LDR     R12,|SMOKEGEN|                 ; -> Word: MemSmoke
        ADD     R12,R12,R1
        LDR     R5,[R12,#&00C] ; get smoke type
        STR     R5,[R0,#4]
        CMP     R5,#SmokeTypeSlowBlack
        MOVEQ   R5,#SlowSmokeFrames                         ; =30
        STREQ   R5,[R0,#0]
        ADD     R0,R0,#BytesPerSmokeHeader
|MAKEPUFFSLOOP|
        LDR     R1,|SMOKEGENOFFSET|                  ; -> Word: &00000000
        LDR     R12,|SMOKEGEN|                 ; -> Word: MemSmoke
        ADD     R12,R12,R1
        LDMIA   R12,{R2-R5}
        STMIA   R0!,{R2-R4} ; store puff position
        LDR     R7,|RANDOM|                  ; -> Word: MemRandom
        LDR     R8,|MAKEPUFFSCOUNT|                  ; -> Word: &00000000
        LDR     R9,|SMOKEORBULLETCOUNT|                  ; -> Word: &00000000
        ADD     R7,R7,R8,LSL #2
        ADD     R7,R7,R9,LSL #2
        LDMIA   R7,{R2-R4}
        MOV     R2,R2,LSL #2
        MOV     R3,R3,LSL #2
        MOV     R4,R4,LSL #2
        CMP     R8,#1
        MOVLT   R2,R2,ASR #1
        MOVLT   R3,R3,ASR #1
        MOVLT   R4,R4,ASR #1
        STMIA   R0!,{R2-R4} ; store puff vector
        LDR     R1,|MAKEPUFFSCOUNT|                  ; -> Word: &00000000
        ADD     R1,R1,#1
        STR     R1,|MAKEPUFFSCOUNT|                  ; -> Word: &00000000
        CMP     R1,#NumPuffs-1
        BLE     |MAKEPUFFSLOOP|
        B       |NEXTSMOKEGEN|                     ; Ends

|CLEARPUFFARRAY|
        LDR     R0,|PUFFARRAY|                  ; -> Word: &0002A5E0, Function entry, (alters flags)
        MOV     R1,#0
        MOV     R2,#0
|CLEARPUFFSLOOP|
        STR     R2,[R0,#0]
        ADD     R0,R0,#4
        ADD     R1,R1,#1
        CMP     R1,#&01,22                      ; =&400
        BLT     |CLEARPUFFSLOOP|
        MOV     PC,R14                          ; Function exit, Ends

|L00002538|
        DCD     MemSmoke                       ;~~~ Word -/-
        DCD     MemRandom                       ;~~ Word -/-
|SMOKEGEN|
        DCD     MemSmoke                       ; Word r/- (referenced)
|RANDOM|
        DCD     MemRandom                       ; Word r/- (referenced)
|RETFROMPUFFSORBULLETS|
        DCD     &00000000                       ; Word r/w (referenced)
|P2MAXCOORDY8|
        DCD     |MAXCOORDY8|
|PFRAMEBUFFERCOPY|
        DCD     |FRAMEBUFFERCOPY|

|COPYDATA|
        ; R0 = address of aircraft data (12 words)
        ; R1 = maximum Y coordinate
        ; R2 = framebuffer address
        STR     R1,|MAXCOORDY7|                  ; -> Word: &00000000, Function entry, (alters flags)

        LDR     R12,|P2MAXCOORDY8|                 ; -> Word: &00014C34
        STR     R1,[R12,#0]

        STR     R2,|FRAMEBUFFER2|                  ; -> Word: &00000000

        LDR     R12,|PFRAMEBUFFERCOPY|                 ; -> Word: &00014C38
        STR     R2,[R12,#0]

        LDMIA   R0,{R1-R12}
        LDR     R0,|PAIRCRAFTDATACOPY|                  ; -> Word: &00013708
        STMIA   R0,{R1-R12}
        MOV     PC,R14                          ; Function exit, Ends

|COPYADDR|
        STR     R3,|PPLAYERINFO15|                  ; -> Word: &00000000, Function entry, (alters flags)
        STR     R5,|P2STATICAIRCRAFTCOORD|                  ; -> Word: &00000000
        STR     R6,|PAIRCRAFTTOCAMERAVECCOPY|                  ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|MAXCOORDY7|
        DCD     &00000000                       ; Word -/w (referenced)
|FRAMEBUFFER2|
        DCD     &00000000                       ; Word r/w (referenced)
|PAIRCRAFTDATACOPY|
        DCD     |AIRCRAFTDATACOPY|
|AIRCRAFTDATACOPY|
        % AircraftThrottle
|PPLAYERINFO15|
        DCD     &00000000                       ; Word r/w (referenced)
|PPLAYER2INFO6|
        DCD     |PLAYER2INFO|
|COSINE2|
        DCD     MemCosine                       ; Word r/- (referenced)
|SINE2|
        DCD     MemSine                       ; Word r/- (referenced)
|P2STATICAIRCRAFTCOORD|
        DCD     &00000000                       ; Word -/w (referenced)
|PAIRCRAFTTOCAMERAVECCOPY|
        DCD     &00000000                       ; Word -/w (referenced)
        DCD     |PPLAYERINFO2|
|TARGETARRAYWRITEOFFSET|
        DCD     &00000000                       ; Word r/w (referenced)
        DCD     &124F8000                       ;~~ Word -/-
|MANOEUVRE|
        DCD     ManoeuvreA                       ; Word r/w (referenced)
|PFRAMECOUNTDOWN1024|
        DCD     |FRAMECOUNTDOWN1024|
|PPREVENTTIMEWARP|
        DCD     |PREVENTTIMEWARP|
|TARGETCOORDX|
        DCD     &00000000                       ; Word array r/w (referenced)
|TARGETCOORDY|
        DCD     &00000000                       ;~~~ Word array r/w (referenced)
|TARGETCOORDZ|
        DCD     &00000000                       ;~~~ Word array r/w (referenced)
|TARGETDAMAGE|
        DCD     &00000000                       ;~~~ Word array r/w (referenced)

|FOLLOWTARGET|
        ; R0 aircraft pointer
        ; R1 AircraftCtrlX
        ; R2 AircraftCtrlY
        ; R3-R5 target vector
        STR     R14,|RETFROMFOLLOWTARGET|           ; -> Word: &00000000, Function entry, (alters flags)
        STR     R0,|AIRCRAFTDATA2|                  ; -> Word: &00000000
        STR     R1,|FOLLOWTARGETCTRLX|              ; -> Word: &00000000
        STR     R2,|FOLLOWTARGETCTRLY|              ; -> Word: &00000000

        MOV     R7,#ManoeuvreA
        STR     R7,|MANOEUVRE|                  ; -> Word: &00000000

        LDR     R7,[R0,#AircraftTargetPtr]                   ; =172
        ADD     R10,R7,#AircraftCoord                     ; =20
        LDMIA   R10,{R7-R9} ; get coordinates of target

        ADR     R11,|TARGETCOORDX|                 ; -> Word array: &00000000
        LDR     R10,[R10,#AircraftDamage-AircraftCoord]                 ; =36
        STMIA   R11,{R7-R10} ; store coordinates and damage of target

        LDR     R9,[R0,#AircraftCtrlX]                   ; =144
        LDR     R10,[R0,#AircraftCtrlY]                  ; =148
        LDR     R11,[R0,#&098]                  ; =152
        LDR     R12,[R0,#&09C]                  ; =156
        SUB     R7,R7,R9
        SUB     R8,R8,R10
        XABS    R7
        XABS    R8

        CMP     R7,R11
        BGT     |TARGETISDYING|

        CMP     R8,R12
        BGT     |TARGETISDYING|

        LDR     R6,[R0,#AircraftType]                   ; =140
        CMP     R6,#ATYPE_GOTHA_G_IV_BOMBER
        CMPNE   R6,#ATYPE_CARGO_AIRCRAFT
        BEQ     |TARGETISDYING|

        CMP     R6,#ATYPE_CAMERA
        BEQ     |L00002694|

        LDR     R6,|TARGETDAMAGE|                  ; -> Word array: &00000000
        CMP     R6,#FatalAircraftDamage                         ; =11
        BGE     |TARGETISDYING|

|L00002694|
        LDR     R6,[R0,#AircraftType]                   ; =140
        CMP     R6,#ATYPE_CAMERA
        LDRNE   R10,[R0,#AircraftTargetDist]  ; =136
        CMPNE   R10,#&3C ; bug?                       ; ="<" (60)

        MUL     R6,R3,R10 ; scale target vector
        MUL     R7,R4,R10
        MUL     R8,R5,R10

        LDR     R3,|TARGETCOORDX|                  ; -> Word array: &00000000
        LDR     R4,|TARGETCOORDY|                  ; -> Word array: &00000000
        LDR     R5,|TARGETCOORDZ|                  ; -> Word array: &00000000

        SUB     R6,R3,R6 ; predict next target position
        SUB     R7,R4,R7
        SUB     R8,R5,R8

        B       |L000026FC|                     ; Ends

|TARGETISDYING|
        LDR     R6,[R0,#AircraftType]                   ; =140
        CMP     R6,#ATYPE_GOTHA_G_IV_BOMBER
        CMPNE   R6,#ATYPE_CARGO_AIRCRAFT
        LDR     R6,[R0,#AircraftCtrlX]                   ; =144
        LDR     R7,[R0,#AircraftCtrlY]                   ; =148
        MOVEQ   R8,#&0A,12                      ; =&A00000
        BEQ     |BIGPLANE|

        LDR     R8,|TARGETCOORDZ|                  ; -> Word array: &00000000
        CMP     R8,#&02,10                      ; =&800000
        MOVLT   R8,#&02,10                      ; =&800000
|BIGPLANE|
        MOV     R1,#&01,22                      ; =&400
        STR     R1,[R0,#AircraftTargetDist]                   ; =136

|L000026FC|
        STR     R6,|PREDICTEDTARGETX|                  ; -> Word: &00000000
        STR     R7,|PREDICTEDTARGETY|                  ; -> Word: &00000000
        STR     R8,|PREDICTEDTARGETZ|                  ; -> Word: &00000000

        LDR     R1,[R0,#AircraftCoordX]                   ; =20
        LDR     R2,[R0,#AircraftCoordY]                   ; =24
        LDR     R3,|PREDICTEDTARGETX|                  ; -> Word: &00000000
        LDR     R4,|PREDICTEDTARGETY|                  ; -> Word: &00000000
        SUB     R11,R3,R1
        SUB     R12,R2,R4
        BL      |FINDANGLE| ; R11,R12 = length of sides, returns angle in R1

        STR     R1,|ANGLETOPREDICTEDTARGETY|                  ; -> Word: &00000000

        LDR     R0,|AIRCRAFTDATA2|                  ; -> Word: &00000000
        LDR     R2,[R0,#AircraftHeading]
        MOV     R2,R2,ASR #AngleShift
        BIC     R2,R2,#AngleStepMask
        SUB     R2,R1,R2
        CMP     R2,#HalfTurn                      ; =&B40
        SUBGT   R2,R2,#FullRotation                   ; =&1680
        CMN     R2,#HalfTurn                      ; =&B40
        ADDLT   R2,R2,#FullRotation                   ; =&1680
        MOV     R3,#1
        CMP     R2,#&78                         ; ="x" (120)
        MOVGT   R3,#0
        CMN     R2,#&78                         ; ="x" (120)
        MOVLT   R3,#0

        LDR     R12,[R0,#AircraftTargetDist]                  ; =136
        CMP     R12,#MaxRangeFireGun                       ; ="%" (37)
        MOVGT   R3,#0
        STR     R3,[R0,#AircraftFireGun]                   ; =32

        LDR     R14,[R0,#AircraftType]                  ; =140
        CMP     R14,#ATYPE_CAMERA
        BEQ     |L00002794|

        LDR     R14,[R0,#AircraftDamage]                  ; =56
        CMP     R14,#FatalAircraftDamage                        ; =11
        BGE     |L00002794|

        CMP     R12,#&32                        ; ="2" (50)
        LDRLT   R14,|PPREVENTTIMEWARP|                 ; -> Word: &00015188
        STRLT   PC,[R14,#0] ; don't allow timewarp when enemy near
|L00002794|
        CMP     R12,#&28                        ; ="(" (40)
        BGT     |L00002854|

        CMP     R12,#6
        BLE     |L00002828|

        LDR     R14,[R0,#AircraftTargetPtr]                  ; =172
        LDR     R3,[R14,#AircraftHeading]
        MOV     R3,R3,ASR #AngleShift

        LDR     R14,[R14,#AircraftType]                 ; =140
        CMP     R14,#ATYPE_CAMERA
        ADDEQ   R3,R3,#HalfTurn                   ; =&B40
        CMP     R3,#FullRotation                      ; =&1680
        SUBGT   R3,R3,#FullRotation                   ; =&1680

        LDR     R14,[R0,#AircraftHeading]
        MOV     R14,R14,ASR #AngleShift
        ABSDIFF R14,R14,R3 ; difference between aircraft and target heading

        MOV     R3,R2
        ABS     R3
        CMP     R3,#&07,24                      ; =&700
        BLT     |L00002810|

        CMP     R14,#&01,22                     ; =&400
        BGT     |L00002854|

        LDR     R3,[R0,#AircraftCoordZ]                   ; =28
        CMP     R3,#MaxAltitudeForManoeuvreB
        MOVLT   R14,#ManoeuvreB
        MOVGT   R14,#ManoeuvreC ; bug? r14 may be 0..&400 if altitude == &600000
        CMP     R3,#MaxAltitudeForManoeuvreC
        MOVGT   R14,#ManoeuvreD
        STR     R14,|MANOEUVRE|                 ; -> Word: &00000000

        B       |L00002854|                     ; Ends

|L00002810|
        CMP     R14,#&2B,26                     ; =&AC0
        BLT     |L00002854|

        CMP     R3,#&8C                         ; ="" (140)
        MOVLT   R14,#ManoeuvreE
        STRLT   R14,|MANOEUVRE|                 ; -> Word: &00000000

        B       |L00002854|                     ; Ends

|L00002828|
        LDR     R3,[R0,#AircraftCoordZ]                   ; =28
        LDR     R14,|TARGETCOORDZ|                 ; -> Word array: &00000000
        SUB     R3,R3,R14 ; vertical distance to target
        CMP     R3,#&02,14                      ; =&80000
        BGT     |L00002854|

        CMN     R3,#&02,14                      ; =&80000
        BLT     |L00002854|

        CMP     R3,#0
        MOVGT   R14,#ManoeuvreE
        MOVLT   R14,#ManoeuvreF
        STR     R14,|MANOEUVRE|                 ; -> Word: &00000000

|L00002854|
        LDR     R3,[R0,#AircraftType]                   ; =140
        CMP     R3,#ATYPE_FOKKER_VIII_TRIPLANE
        CMPNE   R3,#ATYPE_FOKKER_DE5_BIPLANE
        CMPNE   R3,#ATYPE_FOKKER_EINDECKER_IV
        BEQ     |CONTINUEMANOEUVRE|

        LDR     R3,|MANOEUVRE|                  ; -> Word: &00000000
        CMP     R3,#ManoeuvreA
        CMPNE   R3,#ManoeuvreE
        CMPNE   R3,#ManoeuvreF
        BEQ     |CONTINUEMANOEUVRE|

        LDR     R12,|PFRAMECOUNTDOWN1024|                 ; -> Word: &000113F4
        LDR     R12,[R12,#0]
        LDR     R3,[R0,#AircraftEndManoeuvreCount]      ; =168
        CMP     R3,R12
        BGT     |CONTINUEMANOEUVRE|

        MOV     R3,#ManoeuvreA
        STR     R3,|MANOEUVRE|                  ; -> Word: &00000000

|CONTINUEMANOEUVRE|
        LDR     R14,|MANOEUVRE|                 ; -> Word: &00000000
        CMP     R14,#ManoeuvreC
        BNE     |NOTMANOEUVREC|

        LDR     R14,[R0,#AircraftPitch]
        CMP     R14,#&32000                     ; =&32000
        BLT     |NOTMANOEUVREC|

        CMP     R14,#HalfTurn:SHL:AngleShift                     ; =&2D0000
        BGT     |NOTMANOEUVREC|

        MOV     R14,#ManoeuvreA
        STR     R14,|MANOEUVRE|                 ; -> Word: &00000000
|NOTMANOEUVREC|
        LDR     R3,[R0,#AircraftRoll]
        CMP     R3,#&07,14                      ; =&1C0000
        BLE     |L000028DC|

        CMP     R3,#&11,14                      ; =&440000
        BGT     |L000028DC|

        MOV     R14,#ManoeuvreC
        STR     R14,|MANOEUVRE|                 ; -> Word: &00000000
|L000028DC|
        MOV     R12,R2
        ABS     R12
        MOV     R12,R12,ASR #1
        ADD     R12,R12,R12,ASR #1
        ADD     R12,R12,#&4B,30                 ; =&12C

        LDR     R11,[R0,#AircraftEndManoeuvreCount]   ; =168
        CMP     R12,R11
        MOVGT   R12,R11

        LDR     R11,[R0,#AircraftCoordZ]                  ; =28
        CMP     R11,#&32000                     ; =&32000
        MOVLT   R12,R12,ASR #1

        LDR     R3,|MANOEUVRE|                  ; -> Word: &00000000
        CMP     R3,#ManoeuvreA
        BEQ     |L00002938|

        CMP     R3,#ManoeuvreC
        MOVEQ   R2,#QuarterTurn                      ; =&5A0
        MOVEQ   R12,#FullRotation                     ; =&1680
        MOVLT   R2,#0 ; if ManoeuvreB
        MOVGT   R2,#0 ; if ManoeuvreD

        CMP     R3,#ManoeuvreE ; or ManoeuvreF
        MVNGE   R2,#QuarterTurn                      ; =&5A0
        MOVGE   R12,#QuarterTurn                     ; =&5A0

|L00002938|
        CMP     R2,#0
        BGT     |L000029A4|

        LDR     R3,[R0,#AircraftRoll]
        MOV     R3,R3,ASR #AngleShift
        BIC     R3,R3,#AngleStepMask
        LDR     R4,|FOLLOWTARGETCTRLX|                  ; -> Word: &00000000
        CMP     R3,#HalfTurn                      ; =&B40
        BGT     |L00002990|

        CMP     R3,R12 ; bug?
        CMP     R3,R12
        BLT     |L00002974|

        CMP     R4,#0
        MOVGT   R4,#0
        SUB     R4,R4,#&0A                      ; =10
        CMP     R3,R12
|L00002974|
        ADDLT   R4,R4,#3
        STR     R4,|FOLLOWTARGETCTRLX|                  ; -> Word: &00000000

        CMP     R3,#&07,26                      ; =&1C0
        LDRGT   R5,|FOLLOWTARGETCTRLY|                  ; -> Word: &00000000
        SUBGT   R5,R5,#&0A                      ; =10
        STRGT   R5,|FOLLOWTARGETCTRLY|                  ; -> Word: &00000000
        B       |L00002A08|                     ; Ends

|L00002990|
        CMP     R4,#0
        MOVLT   R4,#0
        ADD     R4,R4,#&0A                      ; =10
        STR     R4,|FOLLOWTARGETCTRLX|                  ; -> Word: &00000000
        B       |L00002A08|                     ; Ends

|L000029A4|
        RSB     R12,R12,#FullRotation                 ; =&1680
        LDR     R3,[R0,#AircraftRoll]
        MOV     R3,R3,ASR #AngleShift
        BIC     R3,R3,#AngleStepMask
        LDR     R4,|FOLLOWTARGETCTRLX|                  ; -> Word: &00000000
        CMP     R3,#HalfTurn                      ; =&B40
        BLT     |L000029F4|

        CMP     R3,R12
        BGT     |L000029D8|

        CMP     R4,#0
        MOVLT   R4,#0
        ADD     R4,R4,#&0A                      ; =10
        CMP     R3,R12
|L000029D8|
        SUBGT   R4,R4,#3
        STR     R4,|FOLLOWTARGETCTRLX|                  ; -> Word: &00000000
        CMP     R3,#&53,26                      ; =&14C0
        LDRLT   R5,|FOLLOWTARGETCTRLY|                  ; -> Word: &00000000
        SUBLT   R5,R5,#&0A                      ; =10
        STRLT   R5,|FOLLOWTARGETCTRLY|                  ; -> Word: &00000000
        B       |L00002A08|                     ; Ends

|L000029F4|
        CMP     R4,#0
        MOVGT   R4,#0
        SUB     R4,R4,#&0A                      ; =10
        STR     R4,|FOLLOWTARGETCTRLX|                  ; -> Word: &00000000
        B       |L00002A08|                     ; Ends

|L00002A08|
        LDR     R4,|FOLLOWTARGETCTRLX|                  ; -> Word: &00000000

        CMP     R4,#AircraftCtrlMax                         ; ="d" (100)
        MOVGT   R4,#AircraftCtrlMax                         ; ="d" (100)

        CMN     R4,#AircraftCtrlMax                         ; ="d" (100)
        MVNLT   R4,#AircraftCtrlMax ; bug: sets -AircraftCtrlMax-1

        STR     R4,|FOLLOWTARGETCTRLX|                  ; -> Word: &00000000

        LDR     R2,|ANGLETOPREDICTEDTARGETY|                  ; -> Word: &00000000
        BIC     R2,R2,#AngleStepMask
        LDR     R3,|COSINE2|                  ; -> Word: MemCosine
        LDR     R4,|SINE2|                  ; -> Word: MemSine
        LDR     R5,[R4,R2] ; get sine
        LDR     R6,[R3,R2] ; get cosine

        LDR     R7,[R0,#AircraftCoordX]                   ; =20
        LDR     R8,[R0,#AircraftCoordY]                   ; =24
        LDR     R9,|PREDICTEDTARGETX|                  ; -> Word: &00000000
        LDR     R10,|PREDICTEDTARGETY|                 ; -> Word: &00000000
        SUB     R7,R7,R9 ; vector to predicted target position
        SUB     R8,R8,R10
        MOV     R7,R7,ASR #AngleShift
        MOV     R8,R8,ASR #AngleShift
        MUL     R9,R7,R5 ; x vector to target * sine
        MUL     R10,R8,R6 ; y vector to target * cosine
        XABS    R9
        XABS    R10
        ADD     R7,R9,R10
        MOV     R12,R7,ASR #2
        STR     R12,|TARGETDIST|                 ; -> Word: &00000000

        MOV     R11,R12,ASR #18
        STR     R11,[R0,#AircraftTargetDist]                  ; =136

        LDR     R5,[R0,#AircraftCoordZ]                   ; =28
        LDR     R6,|PREDICTEDTARGETZ|                  ; -> Word: &00000000
        SUB     R11,R5,R6 ; difference from target altitude
        BL      |FINDANGLE| ; R11,R12 = length of sides, returns angle in R1
        STR     R1,|ANGLETOPREDICTEDTARGETX|                  ; -> Word: &00000000

        LDR     R0,|AIRCRAFTDATA2|                  ; -> Word: &00000000
        LDR     R2,[R0,#AircraftAngleW]                   ; =12
        MOV     R2,R2,ASR #AngleShift
        BIC     R2,R2,#AngleStepMask
        SUB     R2,R1,R2
        CMP     R2,#HalfTurn                      ; =&B40
        SUBGT   R2,R2,#FullRotation                   ; =&1680
        CMN     R2,#HalfTurn                      ; =&B40
        ADDLT   R2,R2,#FullRotation                   ; =&1680
        MOV     R12,R2,ASR #2
        XABS    R12
        ADD     R12,R12,#&4B,30                 ; =&12C

        MOV     R3,#0
        CMP     R2,#&8C                         ; ="" (140)
        STRGT   R3,[R0,#AircraftFireGun]                   ; =32
        CMN     R2,#&8C                         ; ="" (140)
        STRLT   R3,[R0,#AircraftFireGun]                   ; =32

        LDR     R5,[R0,#AircraftCoordZ]                   ; =28
        CMP     R5,#&19,18                      ; =&64000
        MVNLT   R2,#&32,28                      ; =&320

        LDR     R3,|MANOEUVRE|                  ; -> Word: &00000000
        CMP     R3,#ManoeuvreA
        BEQ     |L00002B14|

        CMP     R3,#ManoeuvreC
        MVNLT   R2,#&06,24                      ; =&600
        MVNEQ   R2,#&96,30                      ; =&258
        MOVGT   R2,#&01,22                      ; =&400

        CMP     R3,#ManoeuvreE
        MVNEQ   R2,#&32,28                      ; =&320
        MOVGT   R2,#&32,28                      ; =&320

|L00002B14|
        CMP     R2,#0
        BLT     |L00002B60|

        LDR     R3,[R0,#AircraftAngleW]                   ; =12
        MOV     R3,R3,ASR #AngleShift
        BIC     R3,R3,#AngleStepMask
        CMP     R3,#HalfTurn                      ; =&B40
        BGT     |L00002B48|

        LDR     R5,|FOLLOWTARGETCTRLY|                  ; -> Word: &00000000
        CMP     R3,R12
        ADDGT   R5,R5,#&0A                      ; =10
        ADDLT   R5,R5,#5
        STR     R5,|FOLLOWTARGETCTRLY|                  ; -> Word: &00000000
        B       |L00002BA4|                     ; Ends

|L00002B48|
        LDR     R5,|FOLLOWTARGETCTRLY|                  ; -> Word: &00000000
        CMP     R5,#0
        MOVLT   R5,#0
        ADD     R5,R5,#5
        STR     R5,|FOLLOWTARGETCTRLY|                  ; -> Word: &00000000
        B       |L00002BA4|                     ; Ends

|L00002B60|
        RSB     R12,R12,#FullRotation                 ; =&1680
        LDR     R3,[R0,#AircraftAngleW]                   ; =12
        MOV     R3,R3,ASR #AngleShift
        BIC     R3,R3,#AngleStepMask
        CMP     R3,#HalfTurn                      ; =&B40
        BLT     |L00002B90|

        LDR     R5,|FOLLOWTARGETCTRLY|                  ; -> Word: &00000000
        CMP     R3,R12
        SUBLT   R5,R5,#&0A                      ; =10
        SUBGT   R5,R5,#5
        STR     R5,|FOLLOWTARGETCTRLY|                  ; -> Word: &00000000
        B       |L00002BA4|                     ; Ends

|L00002B90|
        LDR     R5,|FOLLOWTARGETCTRLY|                  ; -> Word: &00000000
        CMP     R5,#0
        MOVGT   R5,#0
        SUB     R5,R5,#5
        STR     R5,|FOLLOWTARGETCTRLY|                  ; -> Word: &00000000
|L00002BA4|
        LDR     R4,|FOLLOWTARGETCTRLY|                  ; -> Word: &00000000
        CMP     R4,#&46                         ; ="F" (70)
        MOVGT   R4,#&46                         ; ="F" (70)
        CMN     R4,#&46                         ; ="F" (70)
        MVNLT   R4,#&46                         ; ="F" (70)
        STR     R4,|FOLLOWTARGETCTRLY|                  ; -> Word: &00000000
        LDR     R12,[R0,#AircraftType]                  ; =140
        CMP     R12,#ATYPE_CAMERA
        BEQ     |SETCAMERAANGLES|

        LDR     R1,|FOLLOWTARGETCTRLX|                  ; -> Word: &00000000
        LDR     R2,|FOLLOWTARGETCTRLY|                  ; -> Word: &00000000

        LDR     R14,|RETFROMFOLLOWTARGET|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|SETCAMERAANGLES|
        LDR     R1,|ANGLETOPREDICTEDTARGETY|                  ; -> Word: &00000000
        LDR     R2,|ANGLETOPREDICTEDTARGETX|                  ; -> Word: &00000000
        MOV     R1,R1,LSL #AngleShift
        MOV     R2,R2,LSL #AngleShift
        STR     R1,[R0,#AircraftHeading]
        STR     R2,[R0,#AircraftPitch]

        MOV     R1,#0
        STR     R1,[R0,#AircraftFireGun]                   ; =32

        LDR     R14,|RETFROMFOLLOWTARGET|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|AIRCRAFTDATA2|
        DCD     &00000000                       ; Word r/w (referenced)
|FOLLOWTARGETCTRLX|
        DCD     &00000000                       ; Word r/w (referenced)
|FOLLOWTARGETCTRLY|
        DCD     &00000000                       ; Word r/w (referenced)
|RETFROMFOLLOWTARGET|
        DCD     &00000000                       ; Word r/w (referenced)
|ANGLETOPREDICTEDTARGETY|
        DCD     &00000000                       ; Word r/w (referenced)
|TARGETDIST|
        DCD     &00000000                       ; Word -/w (referenced)
        DCD     &00000000                       ;~ Word -/-
|PREDICTEDTARGETX|
        DCD     &00000000                       ; Word r/w (referenced)
|PREDICTEDTARGETY|
        DCD     &00000000                       ; Word r/w (referenced)
|PREDICTEDTARGETZ|
        DCD     &00000000                       ; Word r/w (referenced)
|ANGLETOPREDICTEDTARGETX|
        DCD     &00000000                       ; Word r/w (referenced)
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-

|ADDFLAK|
        ; R4-R6 = pos of flak gun
        ; R7-R9 = pos to aim at
        LDR     R0,|FLAKARRAY|                  ; -> Word: &0002A4D4, Function entry, (alters flags)
        LDR     R1,|FLAKARRAYOFFSET|                  ; -> Word: &00000000
        ADD     R0,R0,R1
        STMIA   R0!,{R4-R9}
        ADD     R1,R1,#BytesPerFlak                      ; =24
        STR     R1,|FLAKARRAYOFFSET|                  ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|ENEMYBULLETARRAY|
        DCD     &00028B58                       ; Word r/- (referenced)
        DCD     &00000000                       ;~ Word -/-
|FLAKARRAY|
        DCD     &0002A4D4                       ; Word r/- (referenced)
|FLAKARRAYOFFSET|
        DCD     &00000000                       ; Word r/w (referenced)
|BULLETCOUNT|
        DCD     &00000000                       ; Word r/w (referenced)
|UNKNOWNBOOLADDR2|
        DCD     |L000059BC|
|L00002C7C|
        DCD     &00000000                       ; Word -/w (referenced)
|PCAMERA2|
        DCD     |CAMERA|
|SCREENLIMITSPTR3|
        DCD     |MAXCOORDX3|

|SERVICEENEMYBULLETS|
        LDR     R0,|ENEMYBULLETARRAY|                  ; -> Word: &00028B58, Function entry, (alters flags)
        STR     R14,|RETFROMPUFFSORBULLETS|                 ; -> Word: &00000000
        MOV     R2,#0
        STR     R2,|BULLETCOUNT|                  ; -> Word: &00000000
|SERVICEENEMYBULLETSLOOP|
        LDMIA   R0,{R2-R8} ; get position and vector of bullet?

        LDR     R9,|UNKNOWNBOOLADDR2|                  ; -> Word: &00016B2C
        LDR     R9,[R9,#0]
        CMP     R9,#0
        BNE     |STOREBULLETSTATE|

        CMP     R8,#0
        SUBNE   R2,R2,R5 ; add vector to bullet position
        SUBNE   R3,R3,R6
        SUBNE   R4,R4,R7
        BEQ     |NOMOVEBULLET|

        SUB     R8,R8,#1
        CMP     R4,#0
        BGT     |BULLETABOVEGROUND|

        MOV     R5,#SmokeTypeQuickFire
        BL      |ADDSMOKEGEN|
        B       |NOMOVEBULLET|                     ; Ends

|BULLETABOVEGROUND|
        LDR     R12,|PPLAYERINFO15|                 ; -> Word: &00000000
        BL      |CHECKBULLETAGAINSTPLAYER|
        LDR     R12,|PPLAYER2INFO6|                 ; -> Word: &00019CB0
        BL      |CHECKBULLETAGAINSTPLAYER|
        B       |FINISHEDBULLETCOLLCHECKS|                     ; Ends

|CHECKBULLETAGAINSTPLAYER|
        ADD     R12,R12,#AircraftCoord ; =20, Function entry, (alters flags)
        LDMIA   R12,{R9-R11} ; get player's position

        ; Compute distance
        SUB     R9,R9,R2
        SUB     R10,R10,R3
        SUB     R11,R11,R4

        ; Absolute distance
        ABS     R9
        ABS     R10
        ABS     R11

        ; Check for a hit
        CMP     R11,#PlayerBulletCollSizeXYZ    ; =&12C00
        MOVGT   PC,R14                          ; Function exit if GT

        CMP     R10,#PlayerBulletCollSizeXYZ    ; =&12C00
        MOVGT   PC,R14                          ; Function exit if GT

        CMP     R9,#PlayerBulletCollSizeXYZ     ; =&12C00
        MOVGT   PC,R14                          ; Function exit if GT

        ; It's a hit
        LDR     R9,[R12,#AircraftPitch-AircraftCoord] ; =-20
        ADD     R9,R9,#PlayerHitPitchChange           ; =&A000
        STR     R9,[R12,#AircraftPitch-AircraftCoord] ; =-20

        LDR     R9,[R12,#AircraftRoll-AircraftCoord] ; =-12
        ADD     R9,R9,#PlayerHitRollChange           ; =&A000
        STR     R9,[R12,#AircraftRoll-AircraftCoord] ; =-12

        LDR     R9,[R12,#(AircraftDamage-AircraftCoord)] ; =36
        CMP     R9,#FatalAircraftDamage                  ; =11
        LDRLT   R9,[R12,#(AircraftDamage-AircraftCoord)] ; =36
        ADDLT   R9,R9,#1
        STRLT   R9,[R12,#(AircraftDamage-AircraftCoord)] ; =36

        MOV     R8,R0
        MOV     R9,R1
        MOV     R10,R2
        MOV     R11,R3

        MOV     R0,#ChannelMisc
        MOV     R1,#VoiceExplodeMD3
        SWI     Sound_AttachVoice

        MOV     R0,#ChannelMisc
        MVN     R1,#MaxVolume
        MOV     R2,#BulletHitPlayerPitch   ; =&1200
        MOV     R3,#0
        SWI     Sound_Control

        MOV     R0,R8
        MOV     R1,R9
        MOV     R2,R10
        MOV     R3,R11
        MOV     R5,#SmokeTypeQuickFire
        BL      |ADDSMOKEGEN|
        B       |NOMOVEBULLET|                     ; Ends

|FINISHEDBULLETCOLLCHECKS|
        CMP     R8,#&64                         ; ="d" (100)
        BNE     |STOREBULLETSTATE|
        MOV     R5,#SmokeTypeQuickBlack
        BL      |ADDSMOKEGEN|
        B       |NOMOVEBULLET|                     ; Ends

|STOREBULLETSTATE|
        STMIA   R0,{R2-R8} ; Update bullet state
        CMP     R8,#0
        BEQ     |NEXTENEMYBULLET|

        LDR     R1,|PPLAYERINFO15|                  ; -> Word: &00000000
        LDR     R1,[R1,#AircraftViewMap]                   ; =168
        CMP     R1,#0
        BNE     |NEXTENEMYBULLET|

        LDR     R1,|PCAMERA2|                  ; -> Word: &00011B3C
        ADD     R1,R1,#CameraPos                      ; =12
        LDMIA   R1,{R5-R7}

        SUB     R2,R5,R2 ; Make bullet coords relative to camera
        SUB     R3,R6,R3
        SUB     R4,R7,R4

        MOV     R2,R2,ASR #AngleShift
        MOV     R3,R3,ASR #AngleShift
        MOV     R4,R4,ASR #AngleShift

        LDR     R14,|PCAMERA2|                 ; -> Word: &00011B3C
        LDR     R11,[R14,#CameraAngleX]
        MOV     R6,R2
        MOV     R7,R3
        BL      |ROTATE| ; coords R6,R7 (updated), angle R11
        MOV     R2,R6
        MOV     R3,R7

        LDR     R14,|PCAMERA2|                 ; -> Word: &00011B3C
        LDR     R11,[R14,#CameraAngleY]
        MOV     R6,R3
        MOV     R7,R4
        BL      |ROTATE| ; coords R6,R7 (updated), angle R11
        MOV     R3,R6
        MOV     R4,R7

        LDR     R14,|PCAMERA2|                 ; -> Word: &00011B3C
        LDR     R11,[R14,#CameraAngleZ]
        MOV     R6,R2
        MOV     R7,R4
        BL      |ROTATE| ; coords R6,R7 (updated), angle R11
        MOV     R11,R6
        MOV     R12,R7

        ADD     R3,R3,#5
        CMP     R3,#5
        BLT     |NEXTENEMYBULLET|

        STR     R3,|BULLETDIST|                  ; -> Word: &00000000
        CMP     R3,#&C8                         ; ="" (200)
        LDRLT   R8,|BULLETDIVIDENDA|                  ; -> Word: &0000927C
        LDRGE   R8,|L000021BC|                  ; -> Word: &000249F0
        MOVLT   R9,#6
        MOVGE   R9,#8

        CMP     R3,#&01,22                      ; =&400
        LDRGE   R8,|L000021C0|                  ; -> Word: &00124F80
        MOVGE   R9,#&0B                         ; =11

        CMP     R3,#&0A,22                      ; =&2800
        LDRGE   R8,|L000021C4|                  ; -> Word: &00927C00
        MOVGE   R9,#&0E                         ; =14

        MOV     R1,R3 ; divisor

        BL      |DIVIDE| ; returns quotient in R3
        ADD     R12,R12,#&28                    ; ="(" (40)
        MUL     R2,R11,R3
        MOV     R2,R2,ASR R9
        MUL     R4,R12,R3
        MOV     R4,R4,ASR R9

        LDR     R11,|SCREENLIMITSPTR3|                 ; -> Word: &0001142C
        LDMIA   R11,{R11,R12}

        ADD     R2,R2,R11,LSL #(CoordToScreenLog2-1)
        MOV     R2,R2,ASR #CoordToScreenLog2

        ADD     R4,R4,R12,LSL #(CoordToScreenLog2-1)
        MOV     R4,R4,ASR #CoordToScreenLog2

        ; Check whether bullet is on screen
        SUB     R12,R12,#2 ; avoid bullet wrapping from right to left
        CMP     R2,#1
        BLT     |NEXTENEMYBULLET|

        CMP     R4,#1
        BLT     |NEXTENEMYBULLET|

        CMP     R2,R11
        BGT     |NEXTENEMYBULLET|

        CMP     R4,R12
        BGT     |NEXTENEMYBULLET|

        ; Calculate bullet address in frame buffer
        LDR     R11,|FRAMEBUFFER2|                 ; -> Word: &00000000
        MOV     R12,#RowStride                     ; =&140
        MUL     R10,R4,R12
        ADD     R11,R11,R10
        ADD     R11,R11,R2

        ; Draw bullet
        MOV     R9,#OffYellow                         ; ="v" (118)
        LDR     R3,|BULLETDIST|                  ; -> Word: &00000000
        CMP     R3,#&05,18                      ; =&14000
        BGT     |NEXTENEMYBULLET|
        STRB    R9,[R11,#0]
        CMP     R3,#&02,22                      ; =&800
        BGT     |NEXTENEMYBULLET|
        STRB    R9,[R11,#1]
        STRB    R9,[R11,#RowStride]                  ; =5<<6
        STRB    R9,[R11,#(RowStride+1)]                  ; =321
        CMP     R3,#&02,24                      ; =&200
        BGT     |NEXTENEMYBULLET|
        STRB    R9,[R11,#-1]
        STRB    R9,[R11,#RowStride-1]                  ; =319
        STRB    R9,[R11,#-RowStride]                 ; =&3FFFFFB<<6
        STRB    R9,[R11,#-(RowStride-1)]                 ; =-319
        STRB    R9,[R11,#-(RowStride+1)]                 ; =-321
|NEXTENEMYBULLET|
        ADD     R0,R0,#BytesPerEnemyBullet                      ; =" " (32)

        LDR     R1,|BULLETCOUNT|                  ; -> Word: &00000000
        ADD     R1,R1,#1
        STR     R1,|BULLETCOUNT|                  ; -> Word: &00000000

        CMP     R1,#NumBullets                         ; ="" (200)
        BLT     |SERVICEENEMYBULLETSLOOP|

        MOV     R2,#0
        STR     R2,|FLAKARRAYOFFSET|                  ; -> Word: &00000000

        LDR     R14,|RETFROMPUFFSORBULLETS|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|NOMOVEBULLET|
        MOV     R1,#0
        STR     R1,[R0,#&018]                   ; =24
        LDR     R1,|FLAKARRAY|                  ; -> Word: &0002A4D4
        LDR     R2,|FLAKARRAYOFFSET|                  ; -> Word: &00000000
        ADD     R1,R1,R2
        CMP     R2,#0
        BLE     |NEXTENEMYBULLET|

        SUB     R1,R1,#BytesPerFlak                      ; =24
        SUB     R2,R2,#BytesPerFlak                      ; =24
        STR     R2,|FLAKARRAYOFFSET|                  ; -> Word: &00000000

        LDMIA   R1!,{R2-R4}
        LDMIA   R1!,{R7,R8,R14}
        LDR     R5,|COSINE2|                  ; -> Word: MemCosine
        LDR     R6,|SINE2|                  ; -> Word: MemSine

        RSB     R8,R8,#FullRotation                   ; =&1680
        CMP     R8,#0
        ADDLT   R8,R8,#FullRotation                   ; =&1680

        LDR     R9,[R6,R8]
        LDR     R10,[R5,R8]
        LDR     R11,[R5,R7]
        LDR     R12,[R6,R7]
        MUL     R7,R9,R11
        MUL     R8,R10,R11

        MOV     R5,R7,ASR #6
        MOV     R6,R8,ASR #6
        MOV     R7,R12,LSL #6

        MOV     R8,#0
        STMIA   R0!,{R2-R7}
        STR     R8,[R0,#4]

        CMP     R14,#&63                        ; ="c" (99)
        MOVNE   R2,#&46                         ; ="F" (70)
        MOVEQ   R2,#&96                         ; ="" (150)
        STR     R2,[R0,#0]

        SUB     R0,R0,#(BytesPerEnemyBullet - 8)

        MOV     R2,#0
        STR     R2,|L00002C7C|                  ; -> Word: &00000000
        B       |NEXTENEMYBULLET|                     ; Ends

|CLEARENEMYBULLETARRAY|
        LDR     R0,|ENEMYBULLETARRAY|                  ; -> Word: &00028B58, Function entry, (alters flags)
        MOV     R1,#0
        MOV     R2,#0
|CLEARENEMYBULLETLOOP|
        STR     R2,[R0,#0]
        ADD     R0,R0,#4
        ADD     R1,R1,#1
        CMP     R1,#&19,26                      ; =&640
        BLT     |CLEARENEMYBULLETLOOP|
        MOV     PC,R14                          ; Function exit, Ends

|BULLETDIST|
        DCD     &00000000                       ; Word r/w (referenced)
|PLAYER2B|
        DCD     |PLAYER2COORDS|
|PLAYER1B|
        DCD     |PLAYER1COORDS|

|SERVICETARGETS|
        MOV     R5,#0                           ; Function entry, (alters flags)
        STR     R5,|TARGETARRAYWRITEOFFSET|                  ; -> Word: &00000000
        STR     R14,|RETFROMSERVICETARGETS|                 ; -> Word: &00000000
        ADD     R0,R0,#4 ; bug?
        LDR     R1,|PLAYER1B|                  ; -> Word: &00019AB8
        LDMIA   R1,{R1,R2}

        MOV     R12,#(NumPracticeTargets-1)             ; =19

        MVN     R1,R1,ASR #AngleShift
        MVN     R2,R2,ASR #AngleShift

        LDR     R7,|PLAYER2B|                  ; -> Word: &00019CC4
        LDMIA   R7,{R7,R8}
        MVN     R7,R7,ASR #AngleShift
        MVN     R8,R8,ASR #AngleShift

        LDR     R11,|TARGETDATAARRAY|                 ; -> Word: &00000000

|TARGETLOOP2|
        ; r11 = target
        LDR     R3,[R11,#TargetHitpoints]                  ; =28
        CMP     R3,#0
        BLE     |TARGETISDEAD|

        LDMIA   R11,{R3-R5}
        XABSDIFF R6,R1,R3
        CMP     R6,#&05,20                      ; =&5000
        BGT     |CHECKFLAKFORPLAYER2|

        XABSDIFF R6,R2,R4
        CMP     R6,#&05,20                      ; =&5000
        BLT     |CHOOSEFLAK|

|CHECKFLAKFORPLAYER2|
        XABSDIFF R6,R7,R3
        CMP     R6,#&05,20                      ; =&5000
        BGT     |DONEXTTARGET|

        XABSDIFF R6,R8,R4
        CMP     R6,#&05,20                      ; =&5000
        BLT     |CHOOSEFLAK|

|DONEXTTARGET|
        ADD     R11,R11,#1:SHL:BytesPerTargetLog2                   ; =" " (32)
        SUBS    R12,R12,#1
        BPL     |TARGETLOOP2|

        SUB     R0,R0,#4 ; bug?
        LDR     R14,|RETFROMSERVICETARGETS|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|TARGETISDEAD|
        ; r3 = hitpoints remaining
        ; r11 = target
        CMN     R3,#&14 ; -21
        BLT     |CHECKIFTARGETONHITLIST|

        MVN     R3,#&16 ; -23
        STR     R3,[R11,#TargetHitpoints]                  ; =28

        STMFD   R13!,{R0-R12}

        ; Get score increment for the destroyed target type
        LDR     R4,[R11,#TargetType]                  ; =24
        LDR     R5,|PTARGETSCORES|           ; -> Word: &00014654
        ADD     R5,R5,R4,LSL #BytesPerWordLog2
        LDR     R3,[R5,#0] ; score

        ; Update the player's score
        LDR     R4,|PPLAYERINFO15|                  ; -> Word: &00000000
        LDR     R5,[R4,#AircraftScore]                   ; =60
        ADD     R5,R5,R3
        STR     R5,[R4,#AircraftScore]                   ; =60

        ; Add one or more explosions
        LDR     R4,[R11,#TargetType]                  ; =24
        CMP     R4,#TTYPE_PATROL_BOAT
        BGT     |BIGTARGET|

        LDMIA   R11,{R2-R4}
        MOV     R5,#ExplosionStyleSmall                         ; ="c" (99)
        MVN     R2,R2,LSL #10
        MVN     R3,R3,LSL #10
        MVN     R4,R4,LSL #10
        BL      |ADDEXPLOSION|
        LDMFD   R13!,{R0-R12}

|CHECKIFTARGETONHITLIST|
        ; r3 = hitpoints remaining
        LDR     R14,|PRACTICEADDR|                 ; -> Word: &00011FC8
        LDR     R14,[R14,#0]
        CMP     R14,#1
        MVNEQ   R14,#&02,24                     ; =&200
        MOVNE   R14,#&02,2                      ; =&80000000

        SUB     R3,R3,#1
        CMP     R3,R14
        MOVLT   R3,#&0A ; target comes to life?!
        STR     R3,[R11,#TargetHitpoints]                  ; =28

        CMN     R3,#&23                         ; ="#" (35)
        BEQ     |UPDATEHITLISTFORTARGET|
        B       |DONEXTTARGET|                     ; Ends

|BIGTARGET|
        LDR     R4,[R11,#TargetType]                  ; =24
        CMP     R4,#TTYPE_AIRSHIP
        CMPNE   R4,#TTYPE_OIL_TANKER
        CMPNE   R4,#TTYPE_CONTROL_TERMINAL
        CMPNE   R4,#TTYPE_BARRAGE_BALLOON
        CMPNE   R4,#TTYPE_CARGO_AIRCRAFT
        CMPNE   R4,#TTYPE_RAILWAY_STATION
        CMPNE   R4,#TTYPE_BRIDGE
        CMPNE   R4,#TTYPE_FACTORY
        CMPNE   R4,#TTYPE_AIRCRAFT_CARRIER
        MOVEQ   R5,#ExplosionStyleHuge                         ; ="b" (98)
        MOVNE   R5,#ExplosionStyleSmall                         ; ="c" (99)
        LDMIA   R11,{R2-R4}
        MVN     R2,R2,LSL #10
        MVN     R3,R3,LSL #10
        MVN     R4,R4,LSL #10
        BL      |ADDEXPLOSION|
        LDMFD   R13,{R0-R12}
        MOV     R5,#0
        MOV     R6,#0

        LDR     R4,[R11,#TargetType]                  ; =24
        CMP     R4,#TTYPE_AIRSHIP
        CMPNE   R4,#TTYPE_RAILWAY_STATION
        CMPNE   R4,#TTYPE_BRIDGE
        MOVEQ   R6,#&36,26                      ; =&D80
        CMP     R4,#TTYPE_OIL_TANKER
        MOVEQ   R6,#&03,22                      ; =&C00
        CMP     R4,#TTYPE_FACTORY
        MOVEQ   R6,#&05,24                      ; =&500
        CMP     R4,#TTYPE_AIRCRAFT_CARRIER
        MOVEQ   R5,#&03,22                      ; =&C00
        CMP     R4,#TTYPE_CONTROL_TERMINAL
        CMPNE   R4,#TTYPE_BARRAGE_BALLOON
        CMPNE   R4,#TTYPE_GOTHA_G_IV_BOMBER
        CMPNE   R4,#TTYPE_FOKKER_EINDECKER_IV
        CMPNE   R4,#TTYPE_FOKKER_V7_TWIN
        CMPNE   R4,#TTYPE_FOKKER_V3_TRIENGINE
        CMPNE   R4,#TTYPE_CARGO_AIRCRAFT
        CMPNE   R4,#TTYPE_YACHT
        CMPNE   R4,#TTYPE_JET_FIGHTER
        BEQ     |ONLYONEEXPLOSION|

        CMP     R4,#TTYPE_GUN_BOAT
        CMPNE   R4,#TTYPE_TRAIN
        MOVEQ   R6,#&0D,26                      ; =&340
        CMP     R4,#TTYPE_CONTROL_TERMINAL
        MOVEQ   R5,#&02,24                      ; =&200
        MOVEQ   R6,#&02,24                      ; =&200
        CMP     R4,#TTYPE_AIRSHIP
        CMPNE   R4,#TTYPE_OIL_TANKER
        CMPNE   R4,#TTYPE_BRIDGE
        CMPNE   R4,#TTYPE_FACTORY
        CMPNE   R4,#TTYPE_AIRCRAFT_CARRIER
        CMPNE   R4,#TTYPE_RAILWAY_STATION
        MOVEQ   R10,#ExplosionStyleHuge                        ; ="b" (98)
        MOVNE   R10,#ExplosionStyleSmall                        ; ="c" (99)
        LDMIA   R11,{R2-R4}
        ADD     R2,R2,R5
        ADD     R3,R3,R6
        MOV     R5,R10
        MVN     R2,R2,LSL #10
        MVN     R3,R3,LSL #10
        MVN     R4,R4,LSL #10
        BL      |ADDEXPLOSION|
        LDMFD   R13,{R0-R12}
        MOV     R5,#0
        MOV     R6,#0

        LDR     R4,[R11,#TargetType]                  ; =24
        CMP     R4,#TTYPE_AIRSHIP
        CMPNE   R4,#TTYPE_RAILWAY_STATION
        CMPNE   R4,#TTYPE_BRIDGE
        MVNEQ   R6,#&36,26                      ; =&D80
        CMP     R4,#TTYPE_OIL_TANKER
        MVNEQ   R6,#&03,22                      ; =&C00
        CMP     R4,#TTYPE_FACTORY
        MVNEQ   R6,#&05,24                      ; =&500
        CMP     R4,#TTYPE_AIRCRAFT_CARRIER
        MVNEQ   R5,#&03,22                      ; =&C00
        CMP     R4,#TTYPE_GUN_BOAT
        CMPNE   R4,#TTYPE_TRAIN
        MVNEQ   R6,#&0D,26                      ; =&340
        CMP     R4,#TTYPE_CONTROL_TERMINAL
        MVNEQ   R5,#&02,24                      ; =&200
        MVNEQ   R6,#&02,24                      ; =&200
        CMP     R4,#TTYPE_AIRSHIP
        CMPNE   R4,#TTYPE_OIL_TANKER
        CMPNE   R4,#TTYPE_BRIDGE
        CMPNE   R4,#TTYPE_FACTORY
        CMPNE   R4,#TTYPE_AIRCRAFT_CARRIER
        CMPNE   R4,#TTYPE_RAILWAY_STATION
        MOVEQ   R10,#ExplosionStyleHuge                        ; ="b" (98)
        MOVNE   R10,#ExplosionStyleSmall            ; ="c" (99)

        LDMIA   R11,{R2-R4}
        ADD     R2,R2,R5
        ADD     R3,R3,R6
        MOV     R5,R10
        MVN     R2,R2,LSL #10
        MVN     R3,R3,LSL #10
        MVN     R4,R4,LSL #10
        BL      |ADDEXPLOSION|
|ONLYONEEXPLOSION|
        LDMFD   R13!,{R0-R12}
        B       |CHECKIFTARGETONHITLIST|                     ; Ends

|UPDATEHITLISTFORTARGET|
        LDR     R3,|PPLAYER1INFOD|                  ; -> Word: &00019AA4

        ; Ground target destroyed
        LDR     R4,[R11,#TargetType]                  ; =24
        ADD     R4,R4,#TargetTypeToMessage        ; =11
        STR     R4,[R3,#AircraftMsgNum]                   ; =180

        LDR     R3,|PPLAYER2INFO7|                  ; -> Word: &00019CB0
        STR     R4,[R3,#AircraftMsgNum]                   ; =180

        LDR     R3,|PPLAYER1INFOD|                  ; -> Word: &00019AA4
        MOV     R4,#MsgPeriodTargetDestroyed        ; =20
        STR     R4,[R3,#AircraftMsgRemain]                   ; =176

        LDR     R3,|PPLAYER2INFO7|                  ; -> Word: &00019CB0
        STR     R4,[R3,#AircraftMsgRemain]                   ; =176
        STMFD   R13!,{R5}

        LDR     R4,[R11,#TargetType]                  ; =24
        ADD     R4,R4,#TargetTypeToHitList        ; ="2" (50)
        LDR     R3,|HITLIST|                  ; -> Word: MemHitList
        LDRB    R5,[R3,R4]
        ADD     R5,R5,#1
        STRB    R5,[R3,R4]

        LDMFD   R13!,{R5}
        B       |DONEXTTARGET|                     ; Ends

|PPLAYER1INFOD|
        DCD     |PLAYER1INFO|
|PPLAYER2INFO7|
        DCD     |PLAYER2INFO|
        DCD     |MISSIONNUM|
|HITLIST|
        DCD     MemHitList                       ; Word r/- (referenced)

|CHOOSEFLAK|
        ; r11 = target
        LDR     R10,|TARGETARRAYWRITEOFFSET|                 ; -> Word: &00000000
        LDR     R9,|TARGETPTRARRAY2|                  ; -> Word: MemTargetPointerArray
        ADD     R9,R9,R10
        ADD     R10,R10,#BytesPerAddress
        STR     R10,|TARGETARRAYWRITEOFFSET|                 ; -> Word: &00000000
        STR     R11,[R9,#0]

        LDR     R3,[R11,#TargetType]                  ; =24
        CMP     R3,#TTYPE_TANK
        CMPNE   R3,#TTYPE_GROUND_GUN_BASE
        CMPNE   R3,#TTYPE_AIRSHIP
        CMPNE   R3,#TTYPE_GUN_BOAT
        CMPNE   R3,#TTYPE_TRAIN
        CMPNE   R3,#TTYPE_AIRCRAFT_CARRIER
        BNE     |DONEXTTARGET|

        STMFD   R13!,{R0-R12,R14}
        CMP     R3,#TTYPE_AIRSHIP
        BEQ     |AIRSHIP|
        CMP     R3,#TTYPE_GUN_BOAT
        BEQ     |GUNBOAT|
        CMP     R3,#TTYPE_AIRCRAFT_CARRIER
        BEQ     |AIRCRAFTCARRIER|

        ; Tank, ground gun or train
        LDMIA   R11,{R0-R2}
        MVN     R0,R0,LSL #10
        MVN     R1,R1,LSL #10
        SUB     R2,R2,#&64                      ; ="d" (100)
        MVN     R2,R2,LSL #10
        BL      |SERVICEFLAKGUN|

        LDMFD   R13!,{R0-R12,R14}
        B       |DONEXTTARGET|                     ; Ends

|AIRSHIP|
        LDMIA   R11,{R0-R2}
        MVN     R0,R0,LSL #10
        MVN     R1,R1,LSL #10
        MVN     R2,R2,LSL #10
        BL      |SERVICEFLAKGUN|

        LDMFD   R13,{R0-R12,R14}
        LDMIA   R11,{R0-R2}
        MVN     R0,R0,LSL #10
        ADD     R1,R1,#&01,20                   ; =&1000
        MVN     R1,R1,LSL #10
        MVN     R2,R2,LSL #10
        BL      |SERVICEFLAKGUN|

        LDMFD   R13,{R0-R12,R14}
        LDMIA   R11,{R0-R2}
        MVN     R0,R0,LSL #10
        SUB     R1,R1,#&01,20                   ; =&1000
        MVN     R1,R1,LSL #10
        MVN     R2,R2,LSL #10
        BL      |SERVICEFLAKGUN|

        LDMFD   R13!,{R0-R12,R14}
        B       |DONEXTTARGET|                     ; Ends

|GUNBOAT|
        LDMIA   R11,{R0-R2}
        MVN     R0,R0,LSL #10
        ADD     R1,R1,#&01,22                   ; =&400
        MVN     R1,R1,LSL #10
        SUB     R2,R2,#&C8                      ; ="" (200)
        MVN     R2,R2,LSL #10
        BL      |SERVICEFLAKGUN|
        LDMFD   R13,{R0-R12,R14}

        LDMIA   R11,{R0-R2}
        MVN     R0,R0,LSL #10
        SUB     R1,R1,#&01,22                   ; =&400
        MVN     R1,R1,LSL #10
        SUB     R2,R2,#&C8                      ; ="" (200)
        MVN     R2,R2,LSL #10
        BL      |SERVICEFLAKGUN|

        LDMFD   R13!,{R0-R12,R14}
        B       |DONEXTTARGET|                     ; Ends

|AIRCRAFTCARRIER|
        LDMIA   R11,{R0-R2}
        SUB     R2,R2,#&36,26                   ; =&D80
        MVN     R0,R0,LSL #10
        MVN     R1,R1,LSL #10
        MVN     R2,R2,LSL #10
        BL      |SERVICEFLAKGUN|

        LDMFD   R13,{R0-R12,R14}
        LDMIA   R11,{R0-R2}
        SUB     R2,R2,#&36,26                   ; =&D80
        MVN     R1,R1,LSL #10
        ADD     R0,R0,#&02,22                   ; =&800
        MVN     R0,R0,LSL #10
        MVN     R2,R2,LSL #10
        BL      |SERVICEFLAKGUN|

        LDMFD   R13,{R0-R12,R14}
        LDMIA   R11,{R0-R2}
        SUB     R2,R2,#&36,26                   ; =&D80
        MVN     R1,R1,LSL #10
        SUB     R0,R0,#&02,22                   ; =&800
        MVN     R0,R0,LSL #10
        MVN     R2,R2,LSL #10
        BL      |SERVICEFLAKGUN|

        LDMFD   R13!,{R0-R12,R14}
        B       |DONEXTTARGET|                     ; Ends

|RETFROMSERVICETARGETS|
        DCD     &00000000                       ; Word r/w (referenced)
        DCD     &00000000                       ;~ Word -/-
|TARGETDATAARRAY|
        DCD     &00000000                       ; Word r/- (referenced)
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
|TARGETPTRARRAY2|
        DCD     MemTargetPointerArray                       ; Word r/- (referenced)
        DCD     |EXPLOSIONPARAMS|
|NUMTARGETS|
        DCD     &00000000                       ;~ Word -/-
|PRACTICEADDR|
        DCD     |ISPRACTICEMISSION|
|PTARGETSCORES|
        DCD     |TARGETSCORES|
|TARGETSCORES|
        DCD     &000000C8                       ;~~~ Word -/-
        DCD     &0000004B                       ;~~~ Word -/-
        DCD     &0000012C                       ;~~~ Word -/-
        DCD     &00000190                       ;~~ Word -/-
        DCD     &00000096                       ;~~~ Word -/-
        DCD     &00000140                       ;~~~ Word -/-
        DCD     &000003E8                       ;~~~ Word -/-
        DCD     &000000C8                       ;~~~ Word -/-
        DCD     &000001F4                       ;~~ Word -/-
        DCD     &000005DC                       ;~~ Word -/-
        DCD     &00000320                       ;~~~ Word -/-
        DCD     &000002EE                       ;~~~ Word -/-
        DCD     &000001F4                       ;~~ Word -/-
        DCD     &0000015E                       ;~~~ Word -/-
        DCD     &0000012C                       ;~~~ Word -/-
        DCD     &000001F4                       ;~~ Word -/-
        DCD     &0000028A                       ;~~~ Word -/-
        DCD     &000000C8                       ;~~~ Word -/-
        DCD     &000005DC                       ;~~ Word -/-
        DCD     &000007D0                       ;~~ Word -/-
        DCD     &000002BC                       ;~~ Word -/-
        DCD     &00001770                       ;~~~ Word -/-
        DCD     &000003E8                       ;~~~ Word -/-
|PUFFDIVIDENDA|
        DCD     &0000927C                       ; Word r/- (referenced)
|L00003544|
        DCD     &000249F0                       ; Word r/- (referenced)
|L00003548|
        DCD     &00124F80                       ; Word r/- (referenced)
|L0000354C|
        DCD     &00927C00                       ; Word r/- (referenced)
|EXPLOSIONOUTPUT|
        DCD     MemExplosionOut                       ; Word r/- (referenced)
|EXPLOSIONARRAYOFFSET|
        DCD     &00000000                       ; Word r/w (referenced)
|COUNTTO60|
        DCD     &00000000                       ; Word r/w (referenced)
|PREEXPLODECOUNTER|
        DCD     &00000000                       ; Word r/w (referenced)
|COUNT0TO2B|
        DCD     &00000000                       ; Word r/w (referenced)
|COUNTTO13WRAP|
        DCD     &00000000                       ; Word r/w (referenced)
|UNKNOWNBOOLADDR3|
        DCD     |L000059BC|
|L0000356C|
        DCD     &00000000                       ; Word -/w (referenced)

|ADDEXPLOSION|
        ; r5 = 0, 98 or 99
        MOV     R12,#1                          ; Function entry, (alters flags)
        STR     R12,|L0000356C|                 ; -> Word: &00000000
        LDR     R12,|EXPLOSIONARRAYOFFSET|                 ; -> Word: &00000000
        LDR     R11,|EXPLOSIONARRAY|                 ; -> Word: MemExplosionIn
        CMP     R4,#0
        MOVLT   R4,#0
        ADD     R11,R11,R12
        STMIA   R11,{R2-R5}
        ADD     R12,R12,#BytesPerExplosion                    ; =24
        STR     R12,|EXPLOSIONARRAYOFFSET|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|COUNT0TO2C|
        DCD     &00000000                       ; Word r/w (referenced)

|SERVICEEXPLOSIONS|
        MOV     R0,#0                           ; Function entry, (alters flags)
        STR     R0,|COUNT0TO2C|                  ; -> Word: &00000000
        STR     R14,|RETFROMSERVICEEXPLOSIONS|                 ; -> Word: &00000000
|EXPLOSIONLOOP|
        LDR     R0,|EXPLOSIONOUTPUT|                  ; -> Word: MemExplosionOut
        MOV     R2,#0
        STR     R2,|COUNT0TO2B|                  ; -> Word: &00000000

|EXPLOSIONLOOP2|
        LDR     R2,[R0,#0]
        CMP     R2,#0
        BEQ     |GENERATEEXPLOSION|
        SUB     R2,R2,#1

        LDR     R3,|UNKNOWNBOOLADDR3|                  ; -> Word: &00016B2C
        LDR     R3,[R3,#0]
        CMP     R3,#0
        STREQ   R2,[R0,#0]
        STR     R2,|L00003A74|                  ; -> Word: &00000000

        LDR     R2,[R0,#4]
        STR     R2,|USEDARKERGREY|                  ; -> Word: &00000000

        ADD     R0,R0,#8

        MOV     R1,#0
        STR     R1,|COUNTTO60|                  ; -> Word: &00000000
        STR     R1,|L00003A70|                  ; -> Word: &00000000

|L000035F4|
        LDMIA   R0,{R2-R7}

        LDR     R12,|COUNT0TO2C|                 ; -> Word: &00000000
        CMP     R12,#1
        ADDLT   R2,R2,R5,ASR #1
        ADDLT   R3,R3,R6,ASR #1
        ADDLT   R4,R4,R7,ASR #1

        LDR     R12,|L00003A70|                 ; -> Word: &00000000
        MOV     R12,R12,ASR #4
        ADD     R12,R12,#1
        ADDEQ   R2,R2,R5,LSL R12
        ADDEQ   R3,R3,R6,LSL R12
        ADDEQ   R4,R4,R7,LSL R12

        LDR     R12,|L00003A70|                 ; -> Word: &00000000
        MOV     R12,R12,ASR #4
        ADD     R12,R12,#3
        ADDGT   R2,R2,R5,LSL R12
        ADDGT   R3,R3,R6,LSL R12
        ADDGT   R4,R4,R7,LSL R12
        BGE     |L00003688|

        ; first iteration only
        LDR     R12,|COUNTTO13WRAP|                 ; -> Word: &00000000
        ADD     R12,R12,#1
        CMP     R12,#&0D                        ; =13
        MOVGE   R12,#0
        STR     R12,|COUNTTO13WRAP|                 ; -> Word: &00000000
        BLT     |L00003688|

        LDR     R12,|COUNTTO60|                 ; -> Word: &00000000
        TST     R12,#1
        BEQ     |L00003688|

        STMFD   R13!,{R0-R12}
        TST     R2,#8
        MOVEQ   R5,#SmokeTypeQuickFire
        MOVNE   R5,#SmokeTypeQuickBlack
        ADD     R2,R2,R5,LSL #1
        ADD     R3,R3,R6,LSL #1
        ADD     R4,R4,R7,LSL #1
        BL      |ADDSMOKEGEN|
        LDMFD   R13!,{R0-R12}

|L00003688|
        CMP     R4,#0
        MOVLT   R4,#0
        MOVLT   R7,#0
        LDR     R12,|COUNT0TO2C|                 ; -> Word: &00000000
        CMP     R12,#0
        LDREQ   R14,|UNKNOWNBOOLADDR3|                 ; -> Word: &00016B2C
        LDREQ   R14,[R14,#0]
        CMPEQ   R14,#0
        STMEQIA R0,{R2-R7}

        LDR     R1,|PPLAYERINFO7|                  ; -> Word: &00019AA4
        LDR     R1,[R1,#AircraftViewMap]                   ; =168
        CMP     R1,#0
        BNE     |L000038D0|

        LDR     R1,|PCAMERA2|                  ; -> Word: &00011B3C
        ADD     R1,R1,#CameraPos                      ; =12
        LDMIA   R1,{R5-R7}

        SUB     R2,R5,R2 ; Make explosion coords relative to camera
        SUB     R3,R6,R3
        SUB     R4,R7,R4

        MOV     R2,R2,ASR #AngleShift
        MOV     R3,R3,ASR #AngleShift
        MOV     R4,R4,ASR #AngleShift

        LDR     R14,|PCAMERA2|                 ; -> Word: &00011B3C
        LDR     R11,[R14,#CameraAngleX]
        MOV     R6,R2
        MOV     R7,R3
        BL      |ROTATE| ; coords R6,R7 (updated), angle R11
        MOV     R2,R6
        MOV     R3,R7

        LDR     R14,|PCAMERA2|                 ; -> Word: &00011B3C
        LDR     R11,[R14,#CameraAngleY]
        MOV     R6,R3
        MOV     R7,R4
        BL      |ROTATE| ; coords R6,R7 (updated), angle R11
        MOV     R3,R6
        MOV     R4,R7

        LDR     R14,|PCAMERA2|                 ; -> Word: &00011B3C
        LDR     R11,[R14,#CameraAngleZ]
        MOV     R6,R2
        MOV     R7,R4
        BL      |ROTATE| ; coords R6,R7 (updated), angle R11
        MOV     R11,R6
        MOV     R12,R7

        ADD     R3,R3,#5
        CMP     R3,#5
        BLT     |L000038D0|

        CMP     R3,#&C8                         ; ="" (200)
        LDRLT   R8,|PUFFDIVIDENDA|                  ; -> Word: &0000927C
        LDRGE   R8,|L00003544|                  ; -> Word: &000249F0
        MOVLT   R9,#6
        MOVGE   R9,#8

        CMP     R3,#&01,22                      ; =&400
        LDRGE   R8,|L00003548|                  ; -> Word: &00124F80
        MOVGE   R9,#&0B                         ; =11

        CMP     R3,#&0A,22                      ; =&2800
        LDRGE   R8,|L0000354C|                  ; -> Word: &00927C00
        MOVGE   R9,#&0E                         ; =14

        MOV     R1,R3
        BL      |DIVIDE| ; returns quotient in R3
        MUL     R2,R11,R3
        MOV     R2,R2,ASR R9
        MUL     R4,R12,R3
        MOV     R4,R4,ASR R9

        LDR     R12,|COUNT0TO2C|                 ; -> Word: &00000000
        CMP     R12,#0
        BEQ     |L00003820|

        MOV     R3,R4
        LDR     R4,|SCREENLIMITSPTR2|                  ; -> Word: &0001142C
        LDMIA   R4,{R4,R5}

        ADD     R2,R2,R4,LSL #(CoordToScreenLog2-1)
        ADD     R3,R3,R5,LSL #(CoordToScreenLog2-1)

        MOV     R2,R2,ASR #CoordToScreenLog2
        MOV     R3,R3,ASR #CoordToScreenLog2

        SUB     R4,R4,#2
        SUB     R5,R5,#4
        CMP     R2,R4
        BGT     |L000038D0|

        CMP     R2,#1
        BLT     |L000038D0|

        CMP     R3,#2
        BLT     |L000038D0|

        CMP     R3,R5
        BGT     |L000038D0|

        LDR     R11,|FRAMEBUFFER3|                 ; -> Word: &0001204C
        LDR     R11,[R11,#0]
        MOV     R4,#RowStride
        ADD     R11,R11,R2
        MUL     R5,R4,R3
        ADD     R11,R11,R5

        LDR     R5,|COUNTTO60|                  ; -> Word: &00000000
        TST     R5,#2
        MOVEQ   R5,#DarkMaroon
        MOVNE   R5,#Black

        LDR     R12,|COUNT0TO2C|                 ; -> Word: &00000000
        CMP     R12,#1
        STRB    R5,[R11,#0]
        STREQB  R5,[R11,#1]
        STREQB  R5,[R11,#-RowStride]                 ; =&3FFFFFB<<6
        STREQB  R5,[R11,#-(RowStride-1)]                 ; =-319

        B       |L000038D0|                     ; Ends

|FRAMEBUFFER3|
        DCD     |FRAMEBUFFER|
|SCREENLIMITSPTR2|
        DCD     |MAXCOORDX3|

|L00003820|
        LDR     R12,|L00003A70|                 ; -> Word: &00000000
        CMP     R12,#&10                        ; =16
        BEQ     |DRAWEXPLOSION|

        LDR     R11,|LINECOORDS2D|                 ; -> Word: &00014BC8
        ADD     R11,R11,R12
        MOV     R3,R4
        STMIA   R11,{R2,R3}
        ADD     R12,R12,#8
        STR     R12,|L00003A70|                 ; -> Word: &00000000
        B       |L000038D0|                     ; Ends

|DRAWEXPLOSION|
        LDR     R12,|PEXPLOSIONPARAMS|                 ; -> Word: &00014FB0
        STMIA   R12,{R0-R11}

        LDR     R12,|LINECOORDS2D|                 ; -> Word: &00014BC8
        MOV     R5,R4
        MOV     R4,R2
        LDMIA   R12,{R0-R3} ; line coordinates
        LDR     R10,|L00003A74|                 ; -> Word: &00000000
        RSB     R10,R10,#&2D                    ; ="-" (45)
        MOV     R10,R10,ASR #2

        LDR     R9,|COUNTTO60|                  ; -> Word: &00000000
        CMP     R9,#&1E                         ; =30
        MOVGE   R12,#&74                        ; ="t" (116)
        MOVLT   R12,#&17                        ; =23
        SUBLT   R12,R12,R10,ASR #1

        CMP     R9,#&0F                         ; =15
        MOVLT   R12,#&17                        ; =23
        SUBLT   R12,R12,R10,ASR #1

        CMP     R9,#&2D                         ; ="-" (45)
        MOVGT   R12,#&78                        ; ="x" (120)
        SUBGT   R12,R12,R10,ASR #1
        CMP     R12,#MediumRed
        MOVLT   R12,#Black
        CMP     R12,#BrightRed
        BLT     |L000038B0|

        CMP     R12,#Peridot
        MOVLT   R12,#MediumRed

|L000038B0|
        LDR     R10,|USEDARKERGREY|                 ; -> Word: &00000000
        CMP     R10,#1
        MOVEQ   R12,#DarkerGrey
        BL      |DRAWEXPLOSIONPOLYGON|

        MOV     R12,#0
        STR     R12,|L00003A70|                 ; -> Word: &00000000

        LDR     R12,|PEXPLOSIONPARAMS|                 ; -> Word: &00014FB0
        LDMIA   R12,{R0-R11}
|L000038D0|
        ADD     R0,R0,#BytesPerExplosion                ; =24

        LDR     R1,|COUNTTO60|                  ; -> Word: &00000000
        ADD     R1,R1,#1
        STR     R1,|COUNTTO60|                  ; -> Word: &00000000
        CMP     R1,#&3C                         ; ="<" (60)
        BLE     |L000035F4|

|EXPLOSIONDONE|
        LDR     R1,|COUNT0TO2B|                  ; -> Word: &00000000
        ADD     R1,R1,#1
        STR     R1,|COUNT0TO2B|                  ; -> Word: &00000000
        CMP     R1,#2
        BLE     |EXPLOSIONLOOP2|

        MOV     R1,#0
        STR     R1,|EXPLOSIONARRAYOFFSET|                  ; -> Word: &00000000

        LDR     R0,|COUNT0TO2C|                  ; -> Word: &00000000
        ADD     R0,R0,#1
        STR     R0,|COUNT0TO2C|                  ; -> Word: &00000000
        CMP     R0,#2
        BLE     |EXPLOSIONLOOP|

        LDR     R14,|RETFROMSERVICEEXPLOSIONS|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|USEDARKERGREY|
        DCD     &00000000                       ; Word r/w (referenced)
|RETFROMSERVICEEXPLOSIONS|
        DCD     &00000000                       ; Word r/w (referenced)
|PEXPLOSIONPARAMS|
        DCD     |EXPLOSIONPARAMS|

|GENERATEEXPLOSION|
        ; r0 = where to write explosion data
        LDR     R1,|EXPLOSIONARRAYOFFSET|                  ; -> Word: &00000000
        CMP     R1,#0
        ADDEQ   R0,R0,#&17,26                   ; =&5C0
        BEQ     |EXPLOSIONDONE|
        SUB     R1,R1,#BytesPerExplosion            ; =24
        STR     R1,|EXPLOSIONARRAYOFFSET|                  ; -> Word: &00000000

        MOV     R1,#0
        STR     R1,|PREEXPLODECOUNTER|                  ; -> Word: &00000000

        MOV     R1,#&2D                         ; ="-" (45)
        STR     R1,[R0,#0]

        LDR     R1,|EXPLOSIONARRAYOFFSET|                  ; -> Word: &00000000
        LDR     R12,|EXPLOSIONARRAY|                 ; -> Word: MemExplosionIn
        ADD     R12,R12,R1

        LDR     R5,[R12,#&00C] ; bug?                 ; =12
        MOV     R5,#0
        STR     R5,[R0,#4]

        ADD     R0,R0,#8
        MOV     R6,#0
        MOV     R7,#0
        MOV     R8,#0
|PREEXPLODELOOP|
        LDR     R1,|EXPLOSIONARRAYOFFSET|                  ; -> Word: &00000000
        LDR     R12,|EXPLOSIONARRAY|                 ; -> Word: MemExplosionIn
        ADD     R12,R12,R1
        LDMIA   R12,{R2-R5}

        ADD     R2,R2,R6,LSL #1
        ADD     R3,R3,R7,LSL #1
        ADD     R4,R4,R8,LSL #1

        CMP     R5,#ExplosionStyleSmall                         ; ="c" (99)
        ADDEQ   R2,R2,R6,LSL #1
        ADDEQ   R3,R3,R7,LSL #1
        ADDEQ   R4,R4,R8,LSL #1

        CMP     R5,#ExplosionStyleHuge                         ; ="b" (98)
        ADDEQ   R2,R2,R6,LSL #3
        ADDEQ   R3,R3,R7,LSL #3
        ADDEQ   R4,R4,R8,LSL #3

        STMIA   R0!,{R2-R4}

        LDR     R7,|RANDOM2|                  ; -> Word: MemRandom
        LDR     R8,|PREEXPLODECOUNTER|                  ; -> Word: &00000000
        LDR     R9,|COUNT0TO2B|                  ; -> Word: &00000000
        ADD     R7,R7,R8,LSL #4
        ADD     R7,R7,R9,LSL #4
        LDMIA   R7,{R2-R4}

        CMP     R8,#&1E                         ; =30
        MOVLT   R2,R2,LSL #1
        MOVLT   R3,R3,LSL #1
        MOVLT   R4,R4,LSL #1

        CMP     R5,#ExplosionStyleSmall                         ; ="c" (99)
        MOVEQ   R2,R2,LSL #1
        MOVEQ   R3,R3,LSL #1
        MOVEQ   R4,R4,LSL #1

        CMP     R5,#ExplosionStyleHuge                         ; ="b" (98)
        MOVEQ   R2,R2,LSL #3
        MOVEQ   R3,R3,LSL #3
        MOVEQ   R4,R4,LSL #3

        MOV     R6,R2,LSL #2
        MOV     R7,R3,LSL #2
        MOV     R8,R4,LSL #2

        STMIA   R0!,{R6-R8}

        LDR     R1,|PREEXPLODECOUNTER|                  ; -> Word: &00000000
        ADD     R1,R1,#1
        STR     R1,|PREEXPLODECOUNTER|                  ; -> Word: &00000000
        CMP     R1,#&3C                         ; ="<" (60)
        BLE     |PREEXPLODELOOP|

        STMFD   R13!,{R0-R4}

        MOV     R0,#ChannelMisc
        MOV     R1,#VoiceExplode
        SWI     Sound_AttachVoice

        MOV     R0,#ChannelMisc
        MVN     R1,#MaxVolume
        MOV     R2,#ExplosionPitch             ; =&1200
        MOV     R3,#0
        SWI     Sound_Control

        LDMFD   R13!,{R0-R4}
        B       |EXPLOSIONDONE|                     ; Ends

|LINECOORDS2D|
        DCD     |L00003A58|
|L00003A58|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
|L00003A70|
        DCD     &00000000                       ; Word r/w (referenced)
|L00003A74|
        DCD     &00000000                       ; Word r/w (referenced)

|CLEAREXPLOSIONOUTPUT|
        LDR     R0,|EXPLOSIONOUTPUT|                  ; -> Word: MemExplosionOut, Function entry, (alters flags)
        MOV     R1,#0
        MOV     R2,#0
|L00003A84|
        STR     R2,[R0,#0]
        ADD     R0,R0,#4
        ADD     R1,R1,#1
        CMP     R1,#&01,22                      ; =&400
        BLT     |L00003A84|
        MOV     PC,R14                          ; Function exit, Ends

|EXPLOSIONARRAY|
        DCD     MemExplosionIn                       ; Word r/- (referenced)
|RANDOM2|
        DCD     MemRandom                       ; Word r/- (referenced)

|L00003AA4|
        CMP     R1,#&31,22                      ;~~ =&C400
        BGT     |DIVIDE| ; returns quotient in R3                     ;~~
        LDR     R3,|DIVDATA|                  ;~~ -> Word: &00077338
        BIC     R1,R1,#WordAlignMask                        ;~~
        ADD     R3,R3,R1                        ;~~
        LDR     R3,[R3,#0]                      ;~~
        MOV     PC,R14                          ;~~ Function exit, Ends

|DIVDATA|
        DCD     &00077338                       ;~~ Word r/- (referenced)
|MAXCOORDY8|
        DCD     &00000000                       ;~ Word -/-
|FRAMEBUFFERCOPY|
        DCD     &00000000                       ;~ Word -/-

|DRAWEXPLOSIONPOLYGON|
        ; R12 = colour
        LDR     R6,|LINECOORDS2C|                  ; -> Word: &0002FDC0, Function entry
        STMIA   R6,{R0-R5}
        MOV     R0,R6 ; line coordinates
        MOV     R1,R12 ; plot colour
        MOV     R2,#PolygonStyleBlackOutline
        MOV     R12,#3 ; triangle
        MOV     R3,#DrawPolygonNoDarken           ; ="c" (99)
        B       |DRAWPOLYGON|                     ; Ends

|LINECOORDS2C|
        DCD     &0002FDC0                       ; Word r/- (referenced)
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     WIDTH-1                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     |TAKEOFFALTITUDE|
|PPLAYERINFO7|
        DCD     |PLAYER1INFO|
        DCD     |AIRCRAFTDATAARRAYCOPY|
        DCD     &00000000                       ;~ Word -/-

|DRAWSCORE|
        ; r0 = frame buffer address at which to draw the score
        ; r1 = score
        STR     R0,|DRAWCHARSCRADDR|                  ; -> Word: &00000063, Function entry, (alters flags)
        MVN     R4,#0
        MVN     R5,#0
        MVN     R6,#0
        MVN     R7,#0
        MVN     R8,#0
        LDR     R3,|tenthou|                  ; -> Word: &00002710
|tenthousandsloop|
        SUB     R1,R1,R3
        ADD     R4,R4,#1
        CMP     R1,#0
        BGE     |tenthousandsloop|
        ADD     R1,R1,R3
        LDR     R3,|thousand|                  ; -> Word: &000003E8
|thousandsloop|
        SUB     R1,R1,R3
        ADD     R5,R5,#1
        CMP     R1,#0
        BGE     |thousandsloop|
        ADD     R1,R1,R3
        LDR     R3,|hundred|                  ; -> Word: &00000064
|hundredsloop|
        SUB     R1,R1,R3
        ADD     R6,R6,#1
        CMP     R1,#0
        BGE     |hundredsloop|
        ADD     R1,R1,R3
        LDR     R3,|ten|                  ; -> Word: &0000000A
|tensloop|
        SUB     R1,R1,R3
        ADD     R7,R7,#1
        CMP     R1,#0
        BGE     |tensloop|
        ADD     R1,R1,R3
        LDR     R3,|one|                  ; -> Word: &00000001
|onesloop|
        SUB     R1,R1,R3
        ADD     R8,R8,#1
        CMP     R1,#0
        BGE     |onesloop|

        LDR     R3,|CHARINDEXARRAY|                  ; -> Word: &00014DA0
        ADD     R3,R3,#(ScorePrefixLen * IndexSize)          ; =24
        STMIA   R3,{R4-R8} ; store indices of characters to draw

        LDR     R6,|CHARINDEXARRAY|                  ; -> Word: &00014DA0
        LDR     R7,|PFONTDATA|                  ; -> Word: &00014DF0
        LDR     R9,|DRAWCHARSCRADDR|                  ; -> Word: &00000063
        MOV     R4,#Black ; character separator
        MOV     R5,#0 ; init character count
|DRAWCHARLOOP|
        LDR     R1,[R6,#0] ; get character index within the bitmap font data
        ADD     R0,R7,R1,LSL #(CharWidthLog2+CharHeightLog2) ; start of bitmap
        MOV     R3,#0
|DRAWCHARROWLOOP|
        MOV     R2,#0 ; init pixel count
|DRAWCHARPIXLOOP|
        LDRB    R1,[R0,#0]
        STRB    R1,[R9,#0]
        ADD     R0,R0,#1
        ADD     R9,R9,#1
        ADD     R2,R2,#1 ; next pixel
        CMP     R2,#1:SHL:CharWidthLog2
        BLT     |DRAWCHARPIXLOOP| ; next line

        STRB    R4,[R9,#0]
        ADD     R9,R9,#RowStride-(1:SHL:CharWidthLog2)
        ADD     R3,R3,#1
        CMP     R3,#1:SHL:CharHeightLog2
        BLT     |DRAWCHARROWLOOP| ; next character

        ADD     R6,R6,#IndexSize ; next character index

        ; Move to next screen plot address
        LDR     R9,|DRAWCHARSCRADDR|                  ; -> Word: &00000063
        ADD     R9,R9,#(1:SHL:CharWidthLog2)+1
        STR     R9,|DRAWCHARSCRADDR|                  ; -> Word: &00000063

        ADD     R5,R5,#1
        CMP     R5,#ScoreStringLen                   ; =11
        BLT     |DRAWCHARLOOP|

        MOV     PC,R14                          ; Function exit, Ends

|CHARINDEXARRAY|
        DCD     |L00003C30|
|L00003C30|
        DCD     &00000005                       ;~~ Word -/-
        DCD     &0000000A                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &0000000B                       ;~~~ Word -/-
        DCD     &0000000C                       ;~~~ Word -/-
        DCD     &0000000D                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
|PFONTDATA|
        DCD     |FONTDATA|
|DRAWCHARSCRADDR|
        DCD     &00000063                       ; Word r/w (referenced)
|tenthou|
        DCD     10000                       ; Word r/- (referenced)
|thousand|
        DCD     1000                       ; Word r/- (referenced)
|hundred|
        DCD     100                       ; Word r/- (referenced)
|ten|
        DCD     10                       ; Word r/- (referenced)
|one|
        DCD     &00000001                       ; Word r/- (referenced)
|FONTDATA|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &FF00FF00                       ;~~~ Word -/-
        DCD     &FF00FF00                       ;~~~ Word -/-
        DCD     &FF00FF00                       ;~~~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00FF0000                       ;~~~ Word -/-
        DCD     &00FFFF00                       ;~~~ Word -/-
        DCD     &00FF0000                       ;~~~ Word -/-
        DCD     &00FF0000                       ;~~~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &FF000000                       ;~~~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &0000FF00                       ;~~~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &FF000000                       ;~~~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &FF000000                       ;~~~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &000000FF                       ;~~ Word -/-
        DCD     &000000FF                       ;~~ Word -/-
        DCD     &00FF00FF                       ;~~ Word -/-
        DCD     &FFFFFFFF                       ;~ Word -/-
        DCD     &00FF0000                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &0000FF00                       ;~~~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &FF000000                       ;~~~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &0000FF00                       ;~~~ Word -/-
        DCD     &0000FF00                       ;~~~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &FF00FF00                       ;~~~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &FF000000                       ;~~~ Word -/-
        DCD     &FF000000                       ;~~~ Word -/-
        DCD     &00FF0000                       ;~~~ Word -/-
        DCD     &00FF0000                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &FF00FF00                       ;~~~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &FF00FF00                       ;~~~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &FF00FF00                       ;~~~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &FF000000                       ;~~~ Word -/-
        DCD     &FF000000                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &0000FF00                       ;~~~ Word -/-
        DCD     &0000FF00                       ;~~~ Word -/-
        DCD     &0000FF00                       ;~~~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &FF00FF00                       ;~~~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &00FFFF00                       ;~~~ Word -/-
        DCD     &FF00FF00                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &0000FF00                       ;~~~ Word -/-
        DCD     &00FFFF00                       ;~~~ Word -/-
        DCD     &0000FF00                       ;~~~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &FFFFFF00                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
|EXPLOSIONPARAMS|
        % 92

|FINDANGLE|
        ; Finds the angle between two sides of a right-angled triangle
        ; R11 = Length of side A
        ; R12 = Length of side B
        ; Result R1 = angle
        STR     R14,|RETFROMFINDANGLE| ; -> Word: &00000000, Function entry, (alters flags)
        MOV     R11,R11,ASR #AngleShift
        MOV     R12,R12,ASR #AngleShift
        MOV     R9,R11
        MOV     R10,R12

        ABS     R9 ; Magnitude of length of side A
        ABS     R10 ; Magnitude of length of side B

        CMP     R9,R10
        BGT     |SIDEAISLONGER|

        CMP     R12,#0
        BGT     |SIDEBISPOSITIVE|

        MOV     R8,R9,LSL #10 ; opposite, A
        MOV     R1,R10        ; divided by adjacent, B
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R3,R3,LSL #2
        LDR     R7,|ARCTAN|                  ; -> Word: &000203BC
        LDR     R6,[R7,R3] ; angle = arctan(A/B)

        MOV     R1,#HalfTurn                      ; =&B40
        CMP     R11,#0
        ADDLT   R1,R1,R6
        SUBGT   R1,R1,R6
        B       |FOUNDANGLE|                     ; Ends

|SIDEBISPOSITIVE|
        ; R9  = Magnitude of length of side A
        ; R10 = Magnitude of length of side B
        ; R11 = Length of side A
        ; R12 = Length of side B

        MOV     R8,R9,LSL #10 ; opposite, A
        MOV     R1,R10        ; divided by adjacent, B
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R3,R3,LSL #2
        LDR     R7,|ARCTAN|                  ; -> Word: &000203BC
        LDR     R6,[R7,R3] ; angle = arctan(A/B)

        MOV     R1,#0
        CMP     R11,#0
        ADDGT   R1,R1,R6
        SUBLT   R1,R1,R6
        CMP     R1,#0
        ADDLT   R1,R1,#FullRotation                   ; =&1680
        B       |FOUNDANGLE|                     ; Ends

|SIDEAISLONGER| ; Side A is longer than side B
        ; R9  = Magnitude of length of side A
        ; R10 = Magnitude of length of side B
        ; R11 = Length of side A
        ; R12 = Length of side B
        CMP     R11,#0
        BGT     |SIDEAISPOSITIVE|

        MOV     R8,R10,LSL #10 ; opposite, B
        MOV     R1,R9          ; divided by adjacent, A
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R3,R3,LSL #2
        LDR     R7,|ARCTAN|                  ; -> Word: &000203BC
        LDR     R6,[R7,R3] ; angle = arctan(B/A)

        LDR     R1,|THREEQUARTERTURN|                  ; -> Word: &000010E0
        CMP     R12,#0
        ADDGT   R1,R1,R6
        SUBLT   R1,R1,R6
        B       |FOUNDANGLE|                     ; Ends

|SIDEAISPOSITIVE|
        ; R9  = Magnitude of length of side A
        ; R10 = Magnitude of length of side B
        ; R11 = Length of side A
        ; R12 = Length of side B
        MOV     R8,R10,LSL #10 ; opposite, B
        MOV     R1,R9          ; divided by adjacent, A
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R3,R3,LSL #2
        LDR     R7,|ARCTAN|                  ; -> Word: &000203BC
        LDR     R6,[R7,R3] ; angle = arctan(B/A)

        MOV     R1,#QuarterTurn                      ; =&5A0
        CMP     R12,#0
        ADDLT   R1,R1,R6
        SUBGT   R1,R1,R6

|FOUNDANGLE|
        LDR     R14,|RETFROMFINDANGLE|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|ARCTAN|
        DCD     &000203BC                       ; Word r/- (referenced)
|RETFROMFINDANGLE|
        DCD     &00000000                       ; Word r/w (referenced)
|THREEQUARTERTURN|
        DCD     QuarterTurn*3                       ; Word r/- (referenced)
        DCD     &00000000                       ;~ Word -/-

|TARGETAIRCRAFTDESTROYED|
        LDR     R14,[R0,#AircraftType]                  ; =140
        CMP     R14,#ATYPE_CAMERA
        BEQ     |DONECAMERAPLANE|

        ; Target aircraft destroyed
        LDR     R1,|PPLAYER1INFO7|                  ; -> Word: &00019AA4
        STR     R14,[R1,#AircraftMsgNum]                  ; =180

        LDR     R1,|PPLAYER2INFO8|                  ; -> Word: &00019CB0
        STR     R14,[R1,#AircraftMsgNum]                  ; =180

        LDR     R1,|PPLAYER2INFO8|                  ; -> Word: &00019CB0
        MOV     R14,#MsgPeriodTargetDestroyed        ; =20
        STR     R14,[R1,#AircraftMsgRemain]                  ; =176

        LDR     R1,|PPLAYER1INFO7|                  ; -> Word: &00019AA4
        STR     R14,[R1,#AircraftMsgRemain]                  ; =176

        B       |DONECAMERAPLANE|                     ; Ends

|PMISSIONNUM2|
        DCD     |MISSIONNUM|
|VDUVARS|
        DCD     VDUVarDisplayStart                       ;~~ Word -/-
        DCD     VDUVarEndOfList                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
|PPLAYER1INFO7|
        DCD     |PLAYER1INFO|
|PPLAYER2INFO8|
        DCD     |PLAYER2INFO|
|JSENABLE|
        DCD     &00000000                       ; Word r/- (referenced)
|PPLAYERNUM2|
        DCD     |PLAYERNUM|
|REPLAYOVERFLOW|
        DCD     &00000000                       ; Word -/w (referenced)
|REPLAYSTATE|
        DCD     &00000000                       ; Word r/w (referenced)
|REPLAYBUFFERPTR|
        DCD     &000511D8                       ; Word r/w (referenced)
|REPLAYBUFFEREND|
        DCD     &00052178                       ; Word r/- (referenced)
|WRITEREPLAYCTRL|
        DCD     &00000000                       ; Word r/w (referenced)
|READREPLAYCTRL|
        DCD     &00000000                       ; Word r/w (referenced)
|PTIMEWARPCOUNTDOWN|
        DCD     |TIMEWARPCOUNTDOWN|
|PREVENTTIMEWARP|
        DCD     &00000000                       ; Word r/w (referenced)

|READKEYS|
        ; r0 = Player info
        ; r1 = AircraftCtrlX
        ; r2 = AircraftCtrlY
        STR     R14,|RETFROMREADKEYS| ; -> Word: &00000000, Function entry, (alters flags)
        MOV     R10,R0
        MOV     R11,R1
        MOV     R12,R2

        LDR     R14,|PPLAYERNUM2|                 ; -> Word: &0001203C
        LDR     R14,[R14,#0]
        CMP     R14,#0
        SWIEQ   XJoy_Read0
        SWINE   XJoy_Read1                         ; CAUTION: conditional after BL/SWI.
        EOR     R14,R0,#JSMask                   ; =31

        LDR     R0,|JSENABLE|                  ; -> Word: &00000000
        CMP     R0,#0
        MOVEQ   R14,#JSMask                        ; =31

        LDR     R0,|REPLAYSTATE|                  ; -> Word: &00000000
        CMP     R0,#ReplayStateRead
        LDREQ   R0,|REPLAYBUFFERPTR|                  ; -> Word: &000511D8
        LDREQ   R0,[R0,#0]
        MOVNE   R0,#0
        STR     R0,|READREPLAYCTRL|                  ; -> Word: &00000000

        MOV     R0,#0
        STR     R0,|WRITEREPLAYCTRL|                  ; -> Word: &00000000

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyF                         ; ="C" (67)
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOFASTFORWARD|

        LDR     R0,|REPLAYSTATE|                  ; -> Word: &00000000
        CMP     R0,#ReplayStateRead
        BNE     |NOFASTFORWARD|

        LDR     R0,|PTIMEWARPCOUNTDOWN|                  ; -> Word: &000113E0
        LDR     R1,[R0,#0]
        CMP     R1,#0
        MOVEQ   R1,#TimewarpCountdownInit
        STREQ   R1,[R0,#0]

|NOFASTFORWARD|
        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyT
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOSTOPREPLAY|

        LDR     R0,|REPLAYSTATE|                  ; -> Word: &00000000
        CMP     R0,#ReplayStateRead
        BNE     |NOSTOPREPLAY|

        LDR     R0,|MASTERSTATUS|                  ; -> Word: &0001BE9C
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BNE     |NOSTOPREPLAY|

        LDR     R0,|DEMOSTATUS|                  ; -> Word: &00000000
        CMP     R0,#0
        BNE     |NOSTOPREPLAY|

        MOV     R0,#ReplayStateOff
        STR     R0,|REPLAYSTATE|                  ; -> Word: &00000000

        LDR     R0,[R10,#AircraftScore]                  ; =60
        SUB     R0,R0,#ScoreToDeductStopReplay
        STR     R0,[R10,#AircraftScore]                  ; =60

        B       |RESETVIEW|                     ; Ends

|NOSTOPREPLAY|
        LDR     R0,|PTIMEWARPCOUNTDOWN|                  ; -> Word: &000113E0
        LDR     R1,[R0,#0]
        CMP     R1,#0
        LDRGT   R2,[R10,#AircraftSerialBitMask]                  ; =152
        BICGT   R2,R2,#AircraftSerialBitTimewarp                ; ="@" (64)
        STRGT   R2,[R10,#AircraftSerialBitMask]                  ; =152

        LDR     R0,[R10,#AircraftSerialBitMask]                  ; =152
        TST     R0,#AircraftSerialBitTimewarp                         ; ="@" (64)
        BNE     |L0000415C|

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeySpacebar
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOTIMEWARP|

        LDR     R0,|MASTERSTATUS|                  ; -> Word: &0001BE9C
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BNE     |NOTIMEWARP|

        LDR     R0,|PPLAYERNUM3|                  ; -> Word: &0001203C
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BNE     |NOTIMEWARP|
|L0000415C|
        LDR     R0,|PDOGFIGHT2|                  ; -> Word: &00016C38
        LDR     R0,[R0,#0]
        CMP     R0,#1
        BEQ     |NOTIMEWARP|

        LDR     R0,[R10,#AircraftViewMap]                  ; =168
        CMP     R0,#0
        MOVNE   R0,#0
        STRNE   R0,[R10,#AircraftViewMap]                  ; =168
        MOVNE   R0,#NumFramesFullFrontView
        STRNE   R0,|DRAWFULLFRONTVIEWCOUNT|                  ; -> Word: &00000000
        BNE     |NOTIMEWARP|

        LDR     R1,[R10,#PlayerOtherPlayerPtr]                  ; =304
        LDR     R0,[R1,#AircraftViewMap]                   ; =168
        CMP     R0,#0
        MOVNE   R0,#0
        STRNE   R0,[R1,#AircraftViewMap]                   ; =168
        BNE     |NOTIMEWARP|

        LDR     R0,|PREVENTTIMEWARP|                  ; -> Word: &00000000
        CMP     R0,#0
        BEQ     |TIMEWARP|

        LDR     R0,|PMISSIONNUM2|                  ; -> Word: &000177B8
        LDR     R0,[R0,#0]
        CMP     R0,#(MissionFirstPractice-1)   ; =20
        BLE     |BEEP| ; target view or standard mission

        CMP     R0,#(MissionFirstRecon-1)   ; ="d" (100)
        BGE     |BEEP| ; reconnaisance or dogfight

        ; Must be a practice map
        B       |TIMEWARP|                     ; Ends

|BEEP|
        MOV     R0,#ChannelMisc
        MOV     R1,#VoiceBeep
        SWI     Sound_AttachVoice

        MOV     R0,#ChannelMisc
        MVN     R1,#MaxVolume
        MOV     R2,#BeepPitch                 ; =&5000
        MOV     R3,#&14                         ; =20
        SWI     Sound_Control

        B       |NOTIMEWARP|                     ; Ends

|PDOGFIGHT2|
        DCD     |DOGFIGHT|

|TIMEWARP|
        LDR     R0,|PTIMEWARPCOUNTDOWN|                  ; -> Word: &000113E0
        LDR     R1,[R0,#0]
        CMP     R1,#0
        MOVEQ   R1,#TimewarpCountdownInitB
        STREQ   R1,[R0,#0]

        LDR     R0,[R10,#AircraftSerialBitMask]                  ; =152
        TST     R0,#AircraftSerialBitTimewarp                         ; ="@" (64)
        ADDEQ   R0,R0,#AircraftSerialBitTimewarp                      ; ="@" (64)
        STR     R0,[R10,#AircraftSerialBitMask]                  ; =152

|NOTIMEWARP|
        ; Reset the flag so that a fresh event has to prevent timewarp next time
        MOV     R0,#0
        STR     R0,|PREVENTTIMEWARP|                  ; -> Word: &00000000

        LDR     R0,|PTIMEWARPCOUNTDOWN|                  ; -> Word: &000113E0
        LDR     R1,[R0,#0]
        SUBS    R1,R1,#1
        MOVMI   R1,#0
        STR     R1,[R0,#0]

        LDR     R7,[R10,#PlayerGhostPlane]                  ; =268
        LDR     R8,[R7,#AircraftCtrlX]                   ; =144
        LDR     R9,[R7,#AircraftCtrlY]                   ; =148

        TST     R14,#JSClimb
        BEQ     |CLIMB|

        MOV     R0,#ReadKey                         ; ="" (129)
        LDR     R1,[R10,#PlayerKeyClimb]                  ; =188
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOCLIMB|
|CLIMB|
        SUB     R12,R12,#&0A                    ; =10
        CMP     R12,#0
        MOVGT   R12,#0

        SUB     R9,R9,#&0A                      ; =10
        CMP     R9,#0
        MOVGT   R9,#0
|NOCLIMB|
        TST     R14,#JSDive
        BEQ     |DIVE|

        MOV     R0,#ReadKey                         ; ="" (129)
        LDR     R1,[R10,#PlayerKeyDive]                  ; =3<<6
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NODIVE|
|DIVE|
        ADD     R12,R12,#&0A                    ; =10
        CMP     R12,#0
        MOVLT   R12,#0

        ADD     R9,R9,#&0A                      ; =10
        CMP     R9,#0
        MOVLT   R9,#0
|NODIVE|
        TST     R14,#JSLeft
        BEQ     |BANKLEFT|

        MOV     R0,#ReadKey                         ; ="" (129)
        LDR     R1,[R10,#PlayerKeyLeft]                  ; =196
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOBANKLEFT|
|BANKLEFT|
        ; r11 = AircraftCtrlX
        SUB     R11,R11,#&0A                    ; =10
        CMP     R11,#0
        MOVGT   R11,#0

        SUB     R8,R8,#&0A                      ; =10
        CMP     R8,#0
        MOVGT   R8,#0
|NOBANKLEFT|
        TST     R14,#JSRight
        BEQ     |BANKRIGHT|

        MOV     R0,#ReadKey                         ; ="" (129)
        LDR     R1,[R10,#PlayerKeyRight]                  ; =200
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOBANKRIGHT|
|BANKRIGHT|
        ADD     R11,R11,#&0A                    ; =10
        CMP     R11,#0
        MOVLT   R11,#0

        ADD     R8,R8,#&0A                      ; =10
        CMP     R8,#0
        MOVLT   R8,#0
|NOBANKRIGHT|
        LDR     R0,[R10,#PlayerAircraftToView]                  ; =264
        CMP     R0,#CamGhost                         ; ="{" (123)
        BNE     |NOCHOSTCLOSETHROTTLE|

        SUB     R8,R8,R8,ASR #3 ; damping joystick
        SUB     R9,R9,R9,ASR #3

        CMP     R8,#AircraftCtrlMax                         ; ="d" (100)
        MOVGT   R8,#AircraftCtrlMax                         ; ="d" (100)

        CMP     R9,#AircraftCtrlMax                         ; ="d" (100)
        MOVGT   R9,#AircraftCtrlMax                         ; ="d" (100)

        CMN     R8,#(AircraftCtrlMax-1)
        MVNLT   R8,#(AircraftCtrlMax-1) ; correct: sets -AircraftCtrlMax

        CMN     R9,#(AircraftCtrlMax-1)
        MVNLT   R9,#(AircraftCtrlMax-1) ; correct: sets -AircraftCtrlMax

        STR     R8,[R7,#AircraftCtrlX]                   ; =144
        STR     R9,[R7,#AircraftCtrlY]                   ; =148

        MOV     R0,#ReadKey                         ; ="" (129)
        LDR     R1,[R10,#PlayerKeyOpen]                  ; =212
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOGHOSTOPENTHROTTLE|

        LDR     R2,[R10,#PlayerGhostPlane]                  ; =268
        LDR     R3,[R2,#AircraftThrottle]                   ; =48
        ADD     R3,R3,#ThrottleStep                      ; =10
        CMP     R3,#CheatMaxThrottle                      ; =&1F4
        MOVGT   R3,#CheatMaxThrottle                      ; =&1F4
        STR     R3,[R2,#AircraftThrottle]                   ; =48

|NOGHOSTOPENTHROTTLE|
        MOV     R0,#ReadKey                         ; ="" (129)
        LDR     R1,[R10,#PlayerKeyClose]                  ; =208
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOCHOSTCLOSETHROTTLE|

        LDR     R2,[R10,#PlayerGhostPlane]                  ; =268
        LDR     R3,[R2,#AircraftThrottle]                   ; =48
        SUBS    R3,R3,#ThrottleStep                     ; =10
        MOVMI   R3,#0
        STR     R3,[R2,#AircraftThrottle]                   ; =48

|NOCHOSTCLOSETHROTTLE|
        LDR     R2,|READREPLAYCTRL|                  ; -> Word: &00000000
        TST     R2,#ReplayGun
        BNE     |FIREGUN|

        LDR     R2,|REPLAYSTATE|                  ; -> Word: &00000000
        CMP     R2,#ReplayStateRead
        BEQ     |NOFIRE2|

        TST     R14,#JSFire                        ; =16
        BEQ     |FIREGUN|

        MOV     R0,#ReadKey                         ; ="" (129)
        LDR     R1,[R10,#PlayerKeyFire]                  ; =204
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOFIRE2|

        LDR     R0,[R10,#AircraftViewMap]                  ; =168
        CMP     R0,#0
        MOVNE   R0,#0
        STRNE   R0,[R10,#AircraftViewMap]                  ; =168
        MOVNE   R0,#NumFramesFullFrontView
        STRNE   R0,|DRAWFULLFRONTVIEWCOUNT|                  ; -> Word: &00000000
|FIREGUN|
        MOV     R0,#ChannelGun
        MVN     R1,#MaxVolume
        MOV     R2,#GunPitch                      ; =&C00
        MOV     R3,#0
        LDR     R9,[R10,#AircraftDamage]                  ; =56
        CMP     R9,#FatalAircraftDamage                         ; =11
        BGE     |NOFIRE2|

        STR     R0,[R10,#AircraftFireGun]                  ; =32

        LDR     R9,[R10,#AircraftSerialBitMask]                  ; =152
        ADD     R9,R9,#AircraftSerialBitFire
        STR     R9,[R10,#AircraftSerialBitMask]                  ; =152

        SWI     Sound_Control

        LDR     R2,|WRITEREPLAYCTRL|                  ; -> Word: &00000000
        ADD     R2,R2,#ReplayGun
        STR     R2,|WRITEREPLAYCTRL|                  ; -> Word: &00000000

|NOFIRE2|
        LDR     R2,|READREPLAYCTRL|                  ; -> Word: &00000000
        TST     R2,#ReplayCloseThrottle
        BNE     |CLOSETHROTTLE|

        LDR     R2,|REPLAYSTATE|                  ; -> Word: &00000000
        CMP     R2,#ReplayStateRead
        BEQ     |NOCLOSETHROTTLE|

        MOV     R0,#ReadKey                         ; ="" (129)
        LDR     R1,[R10,#PlayerKeyClose]                  ; =208
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOCLOSETHROTTLE|

|CLOSETHROTTLE|
        LDR     R0,[R10,#AircraftThrottle]                  ; =48
        SUB     R0,R0,#ThrottleStep                     ; =10
        CMP     R0,#0
        MOVLT   R0,#0
        STR     R0,[R10,#AircraftThrottle]                  ; =48

        LDR     R9,[R10,#AircraftSerialBitMask]                  ; =152
        ADD     R9,R9,#AircraftSerialBitCloseThrot
        STR     R9,[R10,#AircraftSerialBitMask]                  ; =152

        LDR     R2,|WRITEREPLAYCTRL|                  ; -> Word: &00000000
        ADD     R2,R2,#ReplayCloseThrottle
        STR     R2,|WRITEREPLAYCTRL|                  ; -> Word: &00000000
|NOCLOSETHROTTLE|
        LDR     R2,|READREPLAYCTRL|                  ; -> Word: &00000000
        TST     R2,#ReplayOpenThrottle
        BNE     |OPENTHROTTLE|

        LDR     R2,|REPLAYSTATE|                  ; -> Word: &00000000
        CMP     R2,#ReplayStateRead
        BEQ     |NOOPENTHROTTLE|

        MOV     R0,#ReadKey                         ; ="" (129)
        LDR     R1,[R10,#PlayerKeyOpen]                  ; =212
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOOPENTHROTTLE|

|OPENTHROTTLE|
        LDR     R9,|PCHEATFLAG|                  ; -> Word: &00011FB0
        LDR     R9,[R9,#0]
        CMP     R9,#0
        MOVEQ   R9,#CheatMaxThrottle                      ; =&1F4
        MOVNE   R9,#MaxThrottle                 ; ="d" (100)

        LDR     R0,[R10,#AircraftThrottle]                  ; =48
        ADD     R0,R0,#ThrottleStep                     ; =10
        CMP     R0,R9
        MOVGT   R0,R9
        STR     R0,[R10,#AircraftThrottle]                  ; =48

        LDR     R9,[R10,#AircraftSerialBitMask]                  ; =152
        ADD     R9,R9,#AircraftSerialBitOpenThrot
        STR     R9,[R10,#AircraftSerialBitMask]                  ; =152

        LDR     R2,|WRITEREPLAYCTRL|                  ; -> Word: &00000000
        ADD     R2,R2,#ReplayOpenThrottle
        STR     R2,|WRITEREPLAYCTRL|                  ; -> Word: &00000000

|NOOPENTHROTTLE|
        LDR     R2,|READREPLAYCTRL|                  ; -> Word: &00000000
        TST     R2,#ReplayEnd               ; =&2000
        BNE     |EXIT|

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyF12
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |READKEYS2|

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyQ
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |READKEYS2|

|EXIT|
        LDR     R0,|MASTERSTATUS|                  ; -> Word: &0001BE9C
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BNE     |READKEYS2|

        LDR     R2,|WRITEREPLAYCTRL|                  ; -> Word: &00000000
        ADD     R2,R2,#ReplayEnd                   ; =&2000
        LDR     R3,|REPLAYBUFFERPTR|                  ; -> Word: &000511D8

        STR     R2,[R3,#0]
        ADD     R3,R3,#&10                      ; =16
        STR     R3,|REPLAYBUFFERPTR|                  ; -> Word: &000511D8

        LDR     R2,[R10,#AircraftSerialBitMask]                  ; =152
        ADD     R2,R2,#AircraftSerialBitExit
        STR     R2,[R10,#AircraftSerialBitMask]                  ; =152

        B       |READKEYS2|                     ; Ends

|P6OUTPUT|
        DCD     |OUTPUT|
|PCHEATFLAG|
        DCD     |CHEATFLAG|
|MASTERSTATUS|
        DCD     |SERIALISMASTER|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
|DEBOUNCESPEAKER|
        DCD     &00000000                       ; Word r/w (referenced)
|VOLUME|
        DCD     &0000007F                       ; Word r/w (referenced)
|L0000459C|
        DCD     &00000002                       ; Word r/w (referenced)
|PPLAYERNUM3|
        DCD     |PLAYERNUM|
|PREVENTTIMESKIP|
        DCD     &00000000                       ; Word -/w (referenced)
        DCD     &00000000                       ;~ Word -/-

|READKEYS2|
        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyF1
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOVOLUMEDOWN|

        LDR     R0,|VOLUME|                  ; -> Word: &0000007F
        SUB     R0,R0,#5
        CMP     R0,#1
        MOVLT   R0,#1
        STR     R0,|VOLUME|                  ; -> Word: &0000007F

        SWI     Sound_Volume

|NOVOLUMEDOWN|
        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyF2
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOVOLUMEUP|

        LDR     R0,|VOLUME|                  ; -> Word: &0000007F
        ADD     R0,R0,#5
        CMP     R0,#&7F                         ; =127
        MOVGT   R0,#&7F                         ; =127
        STR     R0,|VOLUME|                  ; -> Word: &0000007F
        SWI     Sound_Volume

|NOVOLUMEUP|
        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyF3
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOSPEAKERCHANGE|

        LDR     R1,|DEBOUNCESPEAKER|                  ; -> Word: &00000000
        CMP     R1,#KeyIsPressed                ; ="" (255)
        BEQ     |NOSPEAKERCHANGE|

        LDR     R0,|L0000459C|                  ; -> Word: &00000002
        CMP     R0,#1
        MOVEQ   R0,#2
        MOVNE   R0,#1
        STR     R0,|L0000459C|                  ; -> Word: &00000002
        SWI     Sound_Speaker

        MOV     R1,#KeyIsPressed                ; ="" (255)
|NOSPEAKERCHANGE|
        STR     R1,|DEBOUNCESPEAKER|                  ; -> Word: &00000000

        LDR     R2,|READREPLAYCTRL|                  ; -> Word: &00000000
        TST     R2,#ReplayToggleCrossHair ; bug?

        LDR     R2,|REPLAYSTATE|                  ; -> Word: &00000000
        CMP     R2,#ReplayStateRead ; bug?

        MOV     R0,#ReadKey                         ; ="" (129)
        LDR     R1,[R10,#PlayerKeyCrosshair]                  ; =216
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOCROSSHAIR|

        LDR     R1,[R10,#PlayerDebounceCrosshair]                  ; =288
        CMP     R1,#KeyIsPressed                ; ="" (255)
        BEQ     |NOCROSSHAIR|

        LDR     R1,[R10,#PlayerCrossHair]                  ; =284
        RSB     R1,R1,#1
        STR     R1,[R10,#PlayerCrossHair]                  ; =284
        MOV     R1,#KeyIsPressed                ; ="" (255)

        LDR     R2,|WRITEREPLAYCTRL|                  ; -> Word: &00000000
        ADD     R2,R2,#ReplayToggleCrossHair
        STR     R2,|WRITEREPLAYCTRL|                  ; -> Word: &00000000

|NOCROSSHAIR|
        STR     R1,[R10,#PlayerDebounceCrosshair]                  ; =288

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyP
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOCHEAT|

        LDR     R0,|MASTERSTATUS|                  ; -> Word: &0001BE9C
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BNE     |NOCHEAT|

        LDR     R9,|L000047E8|                  ; -> Word: &00000000
        CMP     R9,#1
        BEQ     |GETRECONKEYPRESS|

        LDR     R9,[R10,#PlayerAircraftToView]                  ; =264
        CMP     R9,#CamThisPlayer                         ; =20
        MOV     R9,#(MissionFirstRecon-1) ; Prevent save recon photo
        BNE     |GETRECONKEYPRESS|

        LDR     R9,|PPLAYER1INFO8|                  ; -> Word: &00019AA4
        LDR     R9,[R9,#AircraftViewIn]                   ; =44
        CMP     R9,#ViewInside
        MOV     R9,#(MissionFirstRecon-1) ; Prevent save recon photo
        BNE     |GETRECONKEYPRESS|

        LDR     R9,|PMISSIONNUM2|                  ; -> Word: &000177B8
        LDR     R9,[R9,#0]
        CMP     R9,#(MissionFirstRecon-1)                         ; ="d" (100)
        BLT     |GETRECONKEYPRESS|

        CMP     R9,#MissionDogfight                         ; ="k" (107)
        BEQ     |GETRECONKEYPRESS|

        MOV     R0,#SetDisplayBuffer                         ; ="q" (113)
        MOV     R1,#1
        SWI     OS_Byte

        MOV     R0,#SetDrawBuffer                         ; ="p" (112)
        MOV     R1,#1
        SWI     OS_Byte

        MOV     R0,#JoinCursors
        SWI     OS_WriteC

        MOV     R0,#SetCursorPos                         ; =31
        SWI     OS_WriteC

        MOV     R0,#3
        SWI     OS_WriteC

        MOV     R0,#&11                         ; =17
        SWI     OS_WriteC

        ADR     R0,|L000047C4.String|           ; -> String: "SAVE RECONNAISSANCE PICTURE  Y/N",0
        SWI     OS_Write0

        MOV     R9,#0 ; Allow save recon photo
|GETRECONKEYPRESS|
        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeySpacebar
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BEQ     |RECONSPACEPRESS|

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyReturn
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BEQ     |NOCHEAT|

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyN
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BEQ     |NOCHEAT|

        CMP     R9,#0
        BNE     |GETRECONKEYPRESS|

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyY
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BEQ     |SAVEPIC|

        B       |GETRECONKEYPRESS|                     ; Ends

|L000047C4.String|
        DCB     "SAVE RECONNAISSANCE PICTURE  Y/N",0,0,0,0 ; String r/- (referenced)
|L000047E8|
        DCD     &00000000                       ; Word r/w (referenced)
|PPLAYER1INFO8|
        DCD     |PLAYER1INFO|
        DCD     &00000000                       ;~ Word -/-
|THREEQUARTERTURN4|
        DCD     (3*QuarterTurn):SHL:AngleShift                       ; Word r/- (referenced)

|SAVEPIC|
        MOV     R0,#1
        STR     R0,|L000047E8|                  ; -> Word: &00000000
        B       |EXITGAME|                     ; Ends

|ALTENTRYPOINT|
        MOV     R0,#NumFramesFullFrontView                           ;? DCD &E3A00002
        STR     R0,|DRAWFULLFRONTVIEWCOUNT|                  ;? DCD &E58F08E8 -> Word: &00000000

        LDR     R2,|PR13FOREXIT|
        STR     R13,[R2,#0]                     ;? DCD &E582D000

        LDR     R1,|RANDOMSEED|             ;? DCD &E59F1CB4 -> Word: &00011FB4
        STR     R14,[R1,#0]                     ;? DCD &E581E000

        MOV     R0,#JoinCursors                 ;? DCD &E3A00005
        SWI     OS_WriteC                       ;? DCD &EF000000

|RECONSPACEPRESS|
        LDR     R9,|PMISSIONNUM2|                  ; -> Word: &000177B8
        LDR     R9,[R9,#0]
        CMP     R9,#&21                         ; ="!" (33)
        BNE     |NOCHEAT|

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyI
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOCHEAT|

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyE
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOCHEAT|

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyT
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOCHEAT|

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyA
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOCHEAT|

        MOV     R9,#0
        LDR     R8,|PCHEATFLAG|                  ; -> Word: &00011FB0
        STR     R9,[R8,#0]

        B       |NOMAP|                     ; Ends

|NOCHEAT|
        MOV     R0,#ReadKey                         ; ="" (129)
        LDR     R1,[R10,#PlayerKeyMap]                  ; =220
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOMAP|

        LDR     R1,[R10,#PlayerDebounceMap]                  ; =292
        CMP     R1,#KeyIsPressed                ; ="" (255)
        BEQ     |NOMAP|

        LDR     R9,[R10,#AircraftViewMap]                  ; =168
        RSB     R9,R9,#1
        STR     R9,[R10,#AircraftViewMap]                  ; =168
        CMP     R9,#0
        MOVEQ   R9,#NumFramesFullFrontView
        STREQ   R9,|DRAWFULLFRONTVIEWCOUNT|                  ; -> Word: &00000000

        MOV     R1,#KeyIsPressed                ; ="" (255)
|NOMAP|
        STR     R1,[R10,#PlayerDebounceMap]                  ; =292

        MOV     R0,#ReadKey                         ; ="" (129)
        LDR     R1,[R10,#PlayerKeyNoMapView]                  ; =224
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOFRONTVIEW|

        MOV     R9,#0
        STR     R9,[R10,#AircraftViewMap]                  ; =168
        MOV     R9,#NumFramesFullFrontView
        STR     R9,|DRAWFULLFRONTVIEWCOUNT|                  ; -> Word: &00000000

|NOFRONTVIEW|
        LDR     R9,|PDOGFIGHT2|                  ; -> Word: &00016C38
        LDR     R9,[R9,#0]
        CMP     R9,#0
        MOVNE   R9,#0
        STRNE   R9,[R10,#AircraftViewMap]                  ; =168

        LDR     R9,[R10,#AircraftViewMap]                  ; =168
        CMP     R9,#0
        BEQ     |NOMAP2|

        STMFD   R13!,{R0-R12}
        BL      |DRAWMAP|
        LDMFD   R13!,{R0-R12}
|NOMAP2|
        ; r11 = AircraftCtrlX
        ; r12 = AircraftCtrlY
        SUB     R11,R11,R11,ASR #3 ; damping joystick
        SUB     R12,R12,R12,ASR #3

        CMP     R11,#AircraftCtrlMax                        ; ="d" (100)
        MOVGT   R11,#AircraftCtrlMax                        ; ="d" (100)

        CMP     R12,#AircraftCtrlMax                        ; ="d" (100)
        MOVGT   R12,#AircraftCtrlMax                        ; ="d" (100)

        CMN     R11,#(AircraftCtrlMax-1)
        MVNLT   R11,#(AircraftCtrlMax-1) ; correct: sets -AircraftCtrlMax

        CMN     R12,#(AircraftCtrlMax-1)
        MVNLT   R12,#(AircraftCtrlMax-1) ; correct: sets -AircraftCtrlMax

        BL      |SERVICECAMERAZOOM|

        MOV     R9,R10 ; r9 = player info
        LDR     R10,[R10,#PlayerAircraftToViewPtr]                 ; =272
        LDR     R1,[R10,#AircraftPitch]
        LDR     R2,|THREEQUARTERTURN4|                  ; -> Word: &00438000
        CMP     R1,R2
        MOVGT   R0,#0
        MOVLE   R0,#1
        CMP     R1,#QuarterTurn:SHL:AngleShift                      ; =&168000
        MOVLT   R0,#0
        STR     R0,|AIRCRAFTISUPSIDEDOWNOUTSIDEVIEW|                  ; -> Word: &000188D4

        LDR     R2,|READREPLAYCTRL|                  ; -> Word: &00000000
        TST     R2,#ReplayViewFront ; bug?                         ; =16

        LDR     R2,|REPLAYSTATE|                  ; -> Word: &00000000
        CMP     R2,#ReplayStateRead ; bug?

        MOV     R0,#ReadKey                         ; ="" (129)
        LDR     R1,[R9,#PlayerKeyFrontView]                   ; =228
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOFRONTVIEW2|

        STR     PC,|PREVENTTIMESKIP|                  ; -> Word: &00000000

        LDR     R0,[R10,#AircraftViewIn]                  ; =44
        LDR     R1,|AIRCRAFTISUPSIDEDOWNOUTSIDEVIEW|                  ; -> Word: &000188D4
        CMP     R1,#1
        MOVEQ   R2,#QuarterBack
        MOVNE   R2,#QuarterFront
        CMP     R0,#ViewInside
        MOVEQ   R2,#QuarterFront
        STR     R2,[R10,#AircraftViewQuarter]                  ; =36

        MOV     R3,#QuarterTurn                      ; =&5A0
        MUL     R3,R2,R3
        STR     R3,[R10,#AircraftViewAngle]                  ; =40

        LDR     R0,[R10,#AircraftViewIn]                  ; =44
        CMP     R0,#ViewInside
        MOVEQ   R0,#NumFramesFullFrontView
        STREQ   R0,|DRAWFULLFRONTVIEWCOUNT|                  ; -> Word: &00000000

        LDR     R2,|WRITEREPLAYCTRL|                  ; -> Word: &00000000
        ADD     R2,R2,#ReplayViewFront                ; =16
        STR     R2,|WRITEREPLAYCTRL|                  ; -> Word: &00000000
|NOFRONTVIEW2|
        LDR     R2,|READREPLAYCTRL|                  ; -> Word: &00000000
        TST     R2,#ReplayViewLeft ; bug?                        ; =" " (32)

        LDR     R2,|REPLAYSTATE|                  ; -> Word: &00000000
        CMP     R2,#ReplayStateRead ; bug?

        MOV     R0,#ReadKey                         ; ="" (129)
        LDR     R1,[R9,#PlayerKeyLeftView]                   ; =232
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOLEFTVIEW2|

        STR     PC,|PREVENTTIMESKIP|                  ; -> Word: &00000000

        MOV     R0,#QuarterLeft
        STR     R0,[R10,#AircraftViewQuarter]                  ; =36

        MOV     R3,#QuarterTurn                      ; =&5A0
        MUL     R3,R0,R3
        STR     R3,[R10,#AircraftViewAngle]                  ; =40

        LDR     R2,|WRITEREPLAYCTRL|                  ; -> Word: &00000000
        ADD     R2,R2,#ReplayViewLeft                      ; =" " (32)
        STR     R2,|WRITEREPLAYCTRL|                  ; -> Word: &00000000
|NOLEFTVIEW2|
        LDR     R2,|READREPLAYCTRL|                  ; -> Word: &00000000
        TST     R2,#ReplayViewBack ; bug?                         ; ="@" (64)

        LDR     R2,|REPLAYSTATE|                  ; -> Word: &00000000
        CMP     R2,#ReplayStateRead ; bug?

        MOV     R0,#ReadKey                         ; ="" (129)
        LDR     R1,[R9,#PlayerKeyBackView]                   ; =236
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOBACKVIEW|

        STR     PC,|PREVENTTIMESKIP|                  ; -> Word: &00000000
        LDR     R0,[R10,#AircraftViewIn]                  ; =44
        LDR     R1,|AIRCRAFTISUPSIDEDOWNOUTSIDEVIEW|                  ; -> Word: &000188D4
        CMP     R1,#1
        MOVEQ   R2,#QuarterFront
        MOVNE   R2,#QuarterBack
        CMP     R0,#ViewInside
        MOVEQ   R2,#QuarterBack
        STR     R2,[R10,#AircraftViewQuarter]                  ; =36

        MOV     R3,#QuarterTurn                      ; =&5A0
        MUL     R3,R2,R3
        STR     R3,[R10,#AircraftViewAngle]                  ; =40

        LDR     R0,[R10,#AircraftViewIn]                  ; =44
        CMP     R0,#ViewInside
        MOVEQ   R0,#NumFramesFullFrontView
        STREQ   R0,|DRAWFULLFRONTVIEWCOUNT|                  ; -> Word: &00000000

        LDR     R2,|WRITEREPLAYCTRL|                  ; -> Word: &00000000
        ADD     R2,R2,#ReplayViewBack                 ; ="@" (64)
        STR     R2,|WRITEREPLAYCTRL|                  ; -> Word: &00000000
|NOBACKVIEW|
        LDR     R2,|READREPLAYCTRL|                  ; -> Word: &00000000
        TST     R2,#ReplayViewRight ; bug?                        ; ="" (128)

        LDR     R2,|REPLAYSTATE|                  ; -> Word: &00000000
        CMP     R2,#ReplayStateRead ; bug?

        MOV     R0,#ReadKey                         ; ="" (129)
        LDR     R1,[R9,#PlayerKeyRightView]                   ; =240
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NORIGHTVIEW2|

        STR     PC,|PREVENTTIMESKIP|                  ; -> Word: &00000000
        MOV     R0,#QuarterRight
        STR     R0,[R10,#AircraftViewQuarter]                  ; =36

        MOV     R3,#QuarterTurn                      ; =&5A0
        MUL     R3,R0,R3
        STR     R3,[R10,#AircraftViewAngle]                  ; =40

        LDR     R2,|WRITEREPLAYCTRL|                  ; -> Word: &00000000
        ADD     R2,R2,#ReplayViewRight                      ; ="" (128)
        STR     R2,|WRITEREPLAYCTRL|                  ; -> Word: &00000000
|NORIGHTVIEW2|
        LDR     R2,|READREPLAYCTRL|                  ; -> Word: &00000000
        TST     R2,#ReplayToggleViewInOut ; bug                  ; =&100

        LDR     R2,|REPLAYSTATE|                  ; -> Word: &00000000
        CMP     R2,#ReplayStateRead ; bug?

        MOV     R0,#ReadKey                         ; ="" (129)
        LDR     R1,[R9,#PlayerKeyInOutView]                   ; =244
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOTOGGLEINOUTVIEW|

        LDR     R1,[R9,#PlayerDebounceInOutView]                   ; =296
        CMP     R1,#KeyIsPressed                ; ="" (255)
        BEQ     |NOTOGGLEINOUTVIEW|

        STR     PC,|PREVENTTIMESKIP|                  ; -> Word: &00000000

        LDR     R2,|WRITEREPLAYCTRL|                  ; -> Word: &00000000
        ADD     R2,R2,#ReplayToggleViewInOut          ; =&100
        STR     R2,|WRITEREPLAYCTRL|                  ; -> Word: &00000000

        LDR     R0,[R10,#AircraftViewIn]                  ; =44
        RSB     R0,R0,#ViewInside
        STR     R0,[R10,#AircraftViewIn]                  ; =44

        LDR     R1,|AIRCRAFTISUPSIDEDOWNOUTSIDEVIEW|                  ; -> Word: &000188D4
        CMP     R1,#0
        BEQ     |DONESWAPFRONTBACKVIEW|

        LDR     R0,[R10,#AircraftViewQuarter]                  ; =36
        CMP     R0,#QuarterFront ; if front view then change to back
        MOVEQ   R0,#QuarterBack
        STREQ   R0,[R10,#AircraftViewQuarter]                  ; =36
        BEQ     |DONESWAPFRONTBACKVIEW|

        CMP     R0,#QuarterBack ; if back view then change to front
        MOVEQ   R0,#QuarterFront
        STREQ   R0,[R10,#AircraftViewQuarter]                  ; =36

|DONESWAPFRONTBACKVIEW|
        LDR     R0,[R10,#AircraftViewQuarter]                  ; =36
        MOV     R3,#QuarterTurn                      ; =&5A0
        MUL     R3,R0,R3
        STR     R3,[R10,#AircraftViewAngle]                  ; =40

        LDR     R0,[R10,#AircraftViewIn]                  ; =44
        CMP     R0,#ViewInside
        MOV     R1,#KeyIsPressed                ; ="" (255)
        BNE     |NOTOGGLEINOUTVIEW|

        LDR     R0,[R10,#AircraftViewQuarter]                  ; =36
        CMP     R0,#QuarterFront
        MOVEQ   R0,#NumFramesFullFrontView
        STREQ   R0,|DRAWFULLFRONTVIEWCOUNT|                  ; -> Word: &00000000
        MOV     R1,#KeyIsPressed                ; ="" (255)

|NOTOGGLEINOUTVIEW|
        MOV     R10,R9 ; r10 = player info
        STR     R1,[R10,#PlayerDebounceInOutView]                  ; =296

        LDR     R0,|PTIMEWARPCOUNTDOWN|                  ; -> Word: &000113E0
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BNE     |NODRAWFRONTCOCKPIT|

        LDR     R0,|DRAWFULLFRONTVIEWCOUNT|                  ; -> Word: &00000000
        CMP     R0,#0
        BEQ     |NODRAWFRONTCOCKPIT|
        SUB     R0,R0,#1
        STR     R0,|DRAWFULLFRONTVIEWCOUNT|                  ; -> Word: &00000000

        ; Redraw the whole of the cockpit including static regions
        STR     R10,|TMPPLAYERPTR|                 ; -> Word: &00000000
        STR     R11,|PLAYERCTRLX|                 ; -> Word: &00000000
        STR     R12,|PLAYERCTRLY|                 ; -> Word: &00000000
        BL      |MAYBEDRAWFRONTCOCKPIT|
        LDR     R10,|TMPPLAYERPTR|                 ; -> Word: &00000000
        LDR     R11,|PLAYERCTRLX|                 ; -> Word: &00000000
        LDR     R12,|PLAYERCTRLY|                 ; -> Word: &00000000

|NODRAWFRONTCOCKPIT|
        LDR     R0,|MOUSECONFIG|                  ; -> Word: &00000000
        CMP     R0,#MouseDisabled
        BEQ     |NOMOUSECTRL|

        LDR     R0,|PPLAYERNUM4|                  ; -> Word: &0001203C
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BNE     |NOMOUSECTRL|

        SWI     OS_Mouse

        STMFD   R13!,{R0-R3}
        LDR     R0,|MOUSECONFIG|                  ; -> Word: &00000000
        CMP     R0,#MouseEnabled
        BEQ     |DECODEMOUSESTATE|

        MOV     R0,#SetMousePos                         ; =21
        ADR     R1,|L00004C48.Byte_accessed|    ; -> Byte accessed: &03,&00,&00,&00
        SWI     OS_Word

        B       |DECODEMOUSESTATE|                     ; Ends

|L00004C48.Byte_accessed|
        DCB     &03,&00,&00,&00                 ; Byte accessed r/- (referenced)
        DCB     &00,&00,&00,&00                 ; Byte accessed -/-
|PPLAYERNUM4|
        DCD     |PLAYERNUM|
|DEMOSTATUS|
        DCD     &00000000                       ; Word r/- (referenced)
        DCD     |PLAYER2INFO|
|RETFROMREADKEYS|
        DCD     &00000000                       ; Word r/w (referenced)
|AIRCRAFTISUPSIDEDOWNOUTSIDEVIEW|
        DCD     |AIRCRAFTTYPE| ; bug? should be 0 or 1

|DECODEMOUSESTATE|
        ; r10 = player info
        LDMFD   R13!,{R0-R3} ; load mouse state
        ; r0 = x
        ; r1 = y
        ; r2 = buttons

        MOV     R11,R0,ASR #2
        MOV     R12,R1,ASR #2
        LDR     R9,[R10,#PlayerGhostPlane]                  ; =268
        STR     R11,[R9,#AircraftCtrlX]                  ; =144
        STR     R12,[R9,#AircraftCtrlY]                  ; =148

        TST     R2,#MouseButtonLeft
        BEQ     |NOCLOSETHROTTLE3|

        LDR     R3,|WRITEREPLAYCTRL|                  ; -> Word: &00000000
        BIC     R3,R3,#ReplayCloseThrottle
        ADD     R3,R3,#ReplayCloseThrottle
        STR     R3,|WRITEREPLAYCTRL|                  ; -> Word: &00000000

        LDR     R0,[R9,#AircraftThrottle]                   ; =48
        SUBS    R0,R0,#ThrottleStep                     ; =10
        MOVMI   R0,#0
        STR     R0,[R9,#AircraftThrottle]                   ; =48

        LDR     R3,|REPLAYSTATE|                  ; -> Word: &00000000
        CMP     R3,#ReplayStateRead
        BEQ     |NOCLOSETHROTTLE3|

        LDR     R0,[R10,#AircraftThrottle]                  ; =48
        SUB     R0,R0,#ThrottleStep                     ; =10
        CMP     R0,#0
        MOVLT   R0,#0
        STR     R0,[R10,#AircraftThrottle]                  ; =48

        LDR     R0,[R10,#AircraftSerialBitMask]                  ; =152
        TST     R0,#AircraftSerialBitCloseThrot
        ADDEQ   R0,R0,#AircraftSerialBitCloseThrot
        STREQ   R0,[R10,#AircraftSerialBitMask]                  ; =152

|NOCLOSETHROTTLE3|
        TST     R2,#MouseButtonMiddle
        BEQ     |NOOPENTHROTTLE3|

        LDR     R3,|WRITEREPLAYCTRL|                  ; -> Word: &00000000
        BIC     R3,R3,#ReplayOpenThrottle
        ADD     R3,R3,#ReplayOpenThrottle
        STR     R3,|WRITEREPLAYCTRL|                  ; -> Word: &00000000

        LDR     R0,[R9,#AircraftThrottle]                   ; =48
        ADD     R0,R0,#ThrottleStep                      ; =10
        CMP     R0,#CheatMaxThrottle                      ; =&1F4
        MOVGT   R0,#CheatMaxThrottle                      ; =&1F4
        STR     R0,[R9,#AircraftThrottle]                   ; =48

        LDR     R3,|REPLAYSTATE|                  ; -> Word: &00000000
        CMP     R3,#ReplayStateRead
        BEQ     |NOMOUSECTRL|

        LDR     R0,[R10,#AircraftThrottle]                  ; =48
        ADD     R0,R0,#ThrottleStep                      ; =10
        CMP     R0,#MaxThrottle                         ; ="d" (100)
        MOVGT   R0,#MaxThrottle                         ; ="d" (100)
        STR     R0,[R10,#AircraftThrottle]                  ; =48

        LDR     R0,[R10,#AircraftSerialBitMask]                  ; =152
        TST     R0,#AircraftSerialBitOpenThrot
        ADDEQ   R0,R0,#AircraftSerialBitOpenThrot
        STREQ   R0,[R10,#AircraftSerialBitMask]                  ; =152

|NOOPENTHROTTLE3|
        LDR     R3,|REPLAYSTATE|                  ; -> Word: &00000000
        CMP     R3,#ReplayStateRead
        BEQ     |NOMOUSECTRL|

        TST     R2,#MouseButtonRight
        BEQ     |NOMOUSECTRL|

        LDR     R0,[R10,#AircraftViewMap]                  ; =168
        CMP     R0,#0
        MOVNE   R0,#0
        STRNE   R0,[R10,#AircraftViewMap]                  ; =168
        MOVNE   R0,#NumFramesFullFrontView
        STRNE   R0,|DRAWFULLFRONTVIEWCOUNT|                  ; -> Word: &00000000

        LDR     R3,|WRITEREPLAYCTRL|                  ; -> Word: &00000000
        BIC     R3,R3,#ReplayGun
        ADD     R3,R3,#ReplayGun
        STR     R3,|WRITEREPLAYCTRL|                  ; -> Word: &00000000

        MOV     R0,#1
        STR     R0,[R10,#AircraftFireGun]                  ; =32

        LDR     R0,[R10,#AircraftSerialBitMask]                  ; =152
        TST     R0,#AircraftSerialBitFire
        ADDEQ   R0,R0,#AircraftSerialBitFire
        STREQ   R0,[R10,#AircraftSerialBitMask]                  ; =152

        MOV     R0,#ChannelGun
        MVN     R1,#MaxVolume
        MOV     R2,#GunPitch                      ; =&C00
        MOV     R3,#0
        LDR     R9,[R10,#AircraftDamage]                  ; =56
        CMP     R9,#FatalAircraftDamage                         ; =11
        SWILT   Sound_Control

|NOMOUSECTRL|
        LDR     R0,|REPLAYSTATE|                  ; -> Word: &00000000
        CMP     R0,#ReplayStateOff
        BEQ     |NOREPLAY|

        CMP     R0,#ReplayStateWrite
        BEQ     |WRITEREPLAY|

        LDR     R2,|READREPLAYCTRL|                  ; -> Word: &00000000
        MOV     R11,R2,LSR #24 ; decode control x
        MOV     R12,R2,LSL #8
        MOV     R12,R12,LSR #24 ; decode control y
        LDR     R3,|REPLAYBUFFERPTR|                  ; -> Word: &000511D8
        B       |NOWRITEREPLAY|                     ; Ends

|WRITEREPLAY|
        ADD     R11,R11,#AircraftSerialCentre                    ; ="x" (120)
        ADD     R12,R12,#AircraftSerialCentre                    ; ="x" (120)
        LDR     R2,|WRITEREPLAYCTRL|                  ; -> Word: &00000000
        ADD     R2,R2,R11,LSL #24 ; encode control x
        ADD     R2,R2,R12,LSL #16 ; encode control y
        LDR     R3,|REPLAYBUFFERPTR|                  ; -> Word: &000511D8
        STR     R2,[R3,#0]

|NOWRITEREPLAY|
        SUB     R11,R11,#AircraftSerialCentre                    ; ="x" (120)
        SUB     R12,R12,#AircraftSerialCentre                    ; ="x" (120)

        MOV     R0,#0
        STR     R0,|REPLAYOVERFLOW|                  ; -> Word: &00000000

        ADD     R3,R3,#ReplayRecordSize
        STR     R3,|REPLAYBUFFERPTR|                  ; -> Word: &000511D8
        STR     R10,|TMPREPLAYPLAYERINFO|                 ; -> Word: &00000000
        STR     R11,|TMPREPLAYCTRLX|                 ; -> Word: &00000000
        STR     R12,|TMPREPLAYCTRLY|                 ; -> Word: &00000000
        LDR     R4,|REPLAYBUFFEREND|                  ; -> Word: &00052178
        CMP     R3,R4
        BLT     |NOREPLAYBUFFEROVERFLOW|

        MOV     R0,#1
        STR     R0,|REPLAYOVERFLOW|                  ; -> Word: &00000000
        B       |EXITGAME|                     ; Ends

|ALTENTRYPOINT2|
        LDR     R2,|PR13FOREXIT|
        STR     R13,[R2,#0]

        LDR     R1,|RANDOMSEED|              ;? DCD &E59F169C -> Word: &00011FB4
        STR     R14,[R1,#0]                     ;? DCD &E581E000

        MOV     R0,#JoinCursors                           ;? DCD &E3A00005
        SWI     OS_WriteC                       ;? DCD &EF000000

|NOREPLAYBUFFEROVERFLOW|
        LDR     R10,|TMPREPLAYPLAYERINFO|                 ; -> Word: &00000000
        LDR     R11,|TMPREPLAYCTRLX|                 ; -> Word: &00000000
        LDR     R12,|TMPREPLAYCTRLY|                 ; -> Word: &00000000
|NOREPLAY|
        LDR     R0,|PDOGFIGHT2|                  ; -> Word: &00016C38
        LDR     R0,[R0,#0]
        CMP     R0,#1
        BEQ     |NOCHANGECAMDIST|

        MOV     R0,#ReadKey                         ; ="" (129)
        LDR     R1,[R10,#PlayerKeySwitchCamera]                  ; =248
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOSWITCHAIRCRAFTCAMERA|

        LDR     R1,[R10,#PlayerDebounceSwitchCamera]                  ; =300
        CMP     R1,#KeyIsPressed                ; ="" (255)
        BEQ     |NOSWITCHAIRCRAFTCAMERA|

|RETRYSWITCHAIRCRAFTCAMERA|
        LDR     R0,[R10,#PlayerAircraftToView]                  ; =264
        ADD     R0,R0,#1
        CMP     R0,#CamLastAircraft           ; ="2" (50)
        MOVGT   R0,#CamOtherPlayer                         ; =21
        CMP     R0,#(CamOtherPlayer+1)         ; =22
        MOVGE   R0,#0
        STR     R0,[R10,#PlayerAircraftToView]                  ; =264

        MOV     R1,#BytesPerAircraft                         ; ="" (184)
        MUL     R2,R1,R0
        LDR     R3,|AIRCRAFTDATAARRAY3|                  ; -> Word: MemAircraftDataArray
        ADD     R3,R3,R2

        CMP     R0,#CamThisPlayer                         ; =20
        MOVEQ   R3,R10 ; this player
        MOVEQ   R4,#NumFramesFullFrontView
        STREQ   R4,|DRAWFULLFRONTVIEWCOUNT|                  ; -> Word: &00000000

        CMP     R0,#CamOtherPlayer                         ; =21
        LDREQ   R3,[R10,#PlayerOtherPlayerPtr]                  ; =304

        LDR     R4,[R3,#AircraftDamage]                   ; =56
        CMP     R4,#FatalAircraftDamage                         ; =11
        BGT     |RETRYSWITCHAIRCRAFTCAMERA| ; already dead

        STR     R3,[R10,#PlayerAircraftToViewPtr]                  ; =272
        STR     PC,|PREVENTTIMESKIP|                  ; -> Word: &00000000

        MOV     R1,#KeyIsPressed                ; ="" (255)
|NOSWITCHAIRCRAFTCAMERA|
        STR     R1,[R10,#PlayerDebounceSwitchCamera]                  ; =300

        MOV     R0,#ReadKey                         ; ="" (129)
        LDR     R1,[R10,#PlayerKeyViewNextAircraft] ; =500
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOVIEWNEXTAIRCRAFT|

        LDR     R1,[R10,#PlayerDebounceViewNextAircraft]   ; =504
        CMP     R1,#KeyIsPressed                ; ="" (255)
        BEQ     |NOVIEWNEXTAIRCRAFT|

|RETRYVIEWNEXTAIRCRAFT|
        LDR     R0,[R10,#PlayerAircraftToViewB]                  ; =496
        ADD     R0,R0,#1
        CMP     R0,#(CamOtherPlayer+1)         ; =22
        MOVGE   R0,#0
        STR     R0,[R10,#PlayerAircraftToViewB]                  ; =496

        MOV     R1,#BytesPerAircraft                         ; ="" (184)
        MUL     R2,R1,R0
        LDR     R3,|AIRCRAFTDATAARRAY3|                  ; -> Word: MemAircraftDataArray
        ADD     R3,R3,R2

        CMP     R0,#CamThisPlayer                         ; =20
        MOVEQ   R3,R10

        CMP     R0,#CamOtherPlayer                         ; =21
        LDREQ   R3,[R10,#PlayerOtherPlayerPtr]                  ; =304

        ; R3=aircraft to view
        LDR     R4,[R3,#AircraftDamage]                   ; =56
        CMP     R4,#FatalAircraftDamage                         ; =11
        BGT     |RETRYVIEWNEXTAIRCRAFT| ; cannot view dead aircraft

        LDR     R4,[R10,#PlayerCameraPlane]                  ; =280
        STR     R3,[R4,#AircraftTargetPtr]                   ; =172
        STR     PC,|PREVENTTIMESKIP|                  ; -> Word: &00000000
        MOV     R1,#KeyIsPressed                ; ="" (255)
|NOVIEWNEXTAIRCRAFT|
        STR     R1,[R10,#PlayerDebounceViewNextAircraft]   ; =504

        MOV     R0,#ReadKey                         ; ="" (129)
        LDR     R1,[R10,#PlayerKeySwitchCameraB]                  ; =252
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOSWITCHCAMERA|

        LDR     R1,[R10,#PlayerDebounceSwitchCameraB]                  ; =308
        CMP     R1,#KeyIsPressed                ; ="" (255)
        BEQ     |NOSWITCHCAMERA|

        STR     PC,|PREVENTTIMESKIP|                  ; -> Word: &00000000
|RETRYSWITCHCAMERA|
        LDR     R0,[R10,#PlayerCameraPlane]                  ; =280
        STR     R0,[R10,#PlayerAircraftToViewPtr]                  ; =272

        LDR     R0,[R10,#PlayerAircraftToView]                  ; =264
        CMP     R0,#CamTarget                  ; ="d" (100)
        MOVLT   R0,#&77                         ; ="w" (119)
        ADD     R0,R0,#1
        CMP     R0,#&7E                         ; ="~" (126)
        MOVGT   R0,#CamTarget                   ; ="d" (100)
        STR     R0,[R10,#PlayerAircraftToView]                  ; =264

        LDR     R1,[R10,#PlayerCameraPlane]                  ; =280
        ADD     R1,R1,#AircraftCoord                      ; =20
        STR     PC,|PREVENTTIMESKIP|                  ; -> Word: &00000000

        CMP     R0,#CamGhost                         ; ="{" (123)
        LDRGE   R2,[R10,#PlayerGhostPlane]                  ; =268
        STRGE   R2,[R10,#PlayerAircraftToViewPtr]                  ; =272

        CMP     R0,#&78                         ; ="x" (120)
        MOVEQ   R2,#0
        MOVEQ   R3,#&02,14                      ; =&80000
        MOVEQ   R4,#&02,14                      ; =&80000
        STMEQIA R1,{R2-R4} ; store new camera plane coordinates
        MOVEQ   R1,#KeyIsPressed                ; ="" (255)
        BEQ     |NOSWITCHCAMERA|

        CMP     R0,#CamGhost                         ; ="{" (123)
        BEQ     |CAMERAONGHOST|

        CMP     R0,#&79                         ; ="y" (121)
        MOVGE   R1,#KeyIsPressed                ; ="" (255)
        BGE     |NOSWITCHCAMERA|

        B       |CAMERAONTARGET|                     ; Ends

|CAMERAONGHOST|
        LDR     R8,|REPLAYSTATE|                  ; -> Word: &00000000
        CMP     R8,#ReplayStateRead
        BEQ     |ACTIVATEGHOST|

        LDR     R8,[R10,#AircraftDamage]                  ; =56
        CMP     R8,#FatalAircraftDamage                         ; =11
        BGE     |ACTIVATEGHOST| ; player is dead

        B       |RETRYSWITCHCAMERA|                     ; Ends

|ACTIVATEGHOST|
        ; Copy the dead player's AircraftAngle, AircraftSpeed and AircraftCoord
        ; into the ghost plane
        LDMIA   R10,{R0-R7}
        LDR     R8,[R10,#PlayerGhostPlane]                  ; =268
        STMIA   R8,{R0-R7}

        MOV     R1,#0
        STR     R1,[R8,#AircraftThrottle]                   ; =48

        MOV     R1,#QuarterFront
        STR     R1,[R8,#AircraftViewQuarter]                   ; =36

        MOV     R1,#ViewInside
        STR     R1,[R8,#AircraftViewIn]                   ; =44
        STR     R1,[R8,#AircraftCtrlX]                   ; =144
        STR     R1,[R8,#AircraftCtrlY]                   ; =148

        MOV     R1,#KeyIsPressed                ; ="" (255)
        B       |NOSWITCHCAMERA|                     ; Ends

|CAMERAONTARGET|
        SUB     R0,R0,#CamTarget                      ; ="d" (100)
        MOV     R0,R0,LSL #BytesPerTargetLog2
        LDR     R2,|PTARGETDATAARRAY5|                  ; -> Word: MemTargetDataArray
        ADD     R2,R2,R0 ; get target address

        LDR     R3,[R2,#TargetHitpoints]                   ; =28
        CMN     R3,#&32                         ; ="2" (50)
        BLT     |RETRYSWITCHCAMERA| ; target is dead

        MOV     R1,#KeyIsPressed                ; ="" (255)
|NOSWITCHCAMERA|
        STR     R1,[R10,#PlayerDebounceSwitchCameraB]                  ; =308

        LDR     R0,[R10,#PlayerAircraftToView]                  ; =264
        CMP     R0,#CamTarget                         ; ="d" (100)
        BLT     |NOTARGETCAM|
        CMP     R0,#&78                         ; ="x" (120)
        BGE     |NOTARGETCAM|

        SUB     R0,R0,#CamTarget                      ; ="d" (100)
        MOV     R0,R0,LSL #BytesPerTargetLog2
        LDR     R2,|PTARGETDATAARRAY5|                  ; -> Word: MemTargetDataArray
        ADD     R2,R2,R0 ; compute target address

        LDR     R5,[R2,#TargetType]                   ; =24
        LDMIA   R2,{R2-R4}
        SUB     R4,R4,#&C8                      ; ="" (200)
        CMP     R5,#&15                         ; =21
        SUBEQ   R4,R4,#&03,22                   ; =&C00
        SUBGT   R4,R4,#&05,22                   ; =&1400

        MVN     R2,R2,LSL #10
        MVN     R3,R3,LSL #10
        MVN     R4,R4,LSL #10

        LDR     R1,[R10,#PlayerCameraPlane]                  ; =280
        ADD     R1,R1,#AircraftCoord                      ; =20
        STMIA   R1,{R2-R4}
|NOTARGETCAM|
        LDR     R0,[R10,#PlayerAircraftToView]                  ; =264
        CMP     R0,#CamBullet                     ; ="|" (124)
        BNE     |NOBULLETCAM|

        LDR     R0,[R10,#PlayerGhostPlane]                  ; =268
        LDR     R1,|PBULLETSARRAY|                  ; -> Word: MemPlayerBulletsArray
        LDMIA   R1,{R1-R3} ; get bullet 0 coordinates

        LDR     R4,|PBULLETPITCH|                  ; -> Word: &00013254
        LDMIA   R4,{R4,R5} ; get firing angles
        MOV     R4,R4,LSL #10 ; convert back to aircraft angles
        MOV     R5,R5,LSL #10
        MOV     R6,#0 ; AircraftRoll
        STMIA   R0,{R4-R6} ; store bullet angles

        ADD     R0,R0,#AircraftCoord                      ; =20
        STMIA   R0,{R1-R3} ; store bullet coordinates

        B       |NOBULLETCAM|                     ; Ends

|PBULLETSARRAY|
        DCD     MemPlayerBulletsArray                       ; Word r/- (referenced)
|PBULLETPITCH|
        DCD     |BULLETPITCH|
|DRAWFULLFRONTVIEWCOUNT|
        DCD     &00000000                       ; Word r/w (referenced)
|PR13FOREXIT|
        DCD     |R13FOREXIT|
|COSINE3|
        DCD     MemCosine                       ; Word r/- (referenced)
|SINE3|
        DCD     MemSine                       ; Word r/- (referenced)

|NOBULLETCAM|
        LDR     R0,[R10,#PlayerAircraftToView]                  ; =264
        CMP     R0,#&7D                         ; ="}" (125)
        BNE     |L00005178|

        LDR     R0,[R10,#PlayerCameraPlane]                  ; =280
        LDR     R0,[R0,#AircraftTargetPtr]                   ; =172
        ADD     R0,R0,#AircraftCoord                      ; =20
        LDMIA   R0,{R0-R2}

        ADD     R2,R2,#&32000 ; increase AircraftCoordZ

        LDR     R3,[R10,#PlayerHighAngleY]                  ; =468
        SUBS    R3,R3,#&0A,18                   ; =&28000
        ADDMI   R3,R3,#FullRotation:SHL:AngleShift                   ; =&5A0000
        STR     R3,[R10,#PlayerHighAngleY]                  ; =468

        LDR     R4,|COSINE3|                  ; -> Word: MemCosine
        LDR     R5,|SINE3|                  ; -> Word: MemSine
        MOV     R6,R3,ASR #12
        MOV     R6,R6,LSL #BytesPerWordLog2
        LDR     R4,[R4,R6] ; get sine
        LDR     R5,[R5,R6] ; get cosine
        ADD     R0,R0,R4,LSL #8
        ADD     R1,R1,R5,LSL #8

        ADD     R3,R3,#QuarterTurn:SHL:AngleShift                   ; =&168000
        ADD     R3,R3,#HalfTurn:SHL:AngleShift                   ; =&2D0000

        LDR     R6,[R10,#PlayerGhostPlane]                  ; =268
        ADD     R7,R6,#AircraftCoord                      ; =20
        STMIA   R7,{R0-R2}

        MOV     R2,#&19,28                      ; =&190
        MOV     R4,#0
        STMIA   R6,{R2-R4} ; store angles

|L00005178|
        LDR     R0,[R10,#PlayerAircraftToView]                  ; =264
        CMP     R0,#&7E                         ; ="~" (126)
        BNE     |L00005244|

        LDR     R0,[R10,#PlayerCameraPlane]                  ; =280
        LDR     R0,[R0,#AircraftTargetPtr]                   ; =172
        ADD     R0,R0,#AircraftCoord                      ; =20
        LDMIA   R0,{R0-R2}

        ADD     R2,R2,#&32000 ; increase AircraftCoordZ

        LDR     R3,[R10,#PlayerHighAngleY]                  ; =468
        SUBS    R3,R3,#&0A,18                   ; =&28000
        ADDMI   R3,R3,#FullRotation:SHL:AngleShift                   ; =&5A0000
        STR     R3,[R10,#PlayerHighAngleY]                  ; =468

        LDR     R8,[R10,#PlayerHighAngleX]                  ; =472
        SUBS    R8,R8,#&0F,20                   ; =&F000
        ADDMI   R8,R8,#FullRotation:SHL:AngleShift                   ; =&5A0000
        STR     R8,[R10,#PlayerHighAngleX]                  ; =472

        LDR     R4,|COSINE3|                  ; -> Word: MemCosine
        LDR     R5,|SINE3|                  ; -> Word: MemSine
        MOV     R6,R3,ASR #12
        MOV     R6,R6,LSL #BytesPerWordLog2
        LDR     R4,[R4,R6]
        LDR     R5,[R5,R6]

        LDR     R6,|COSINE3|                  ; -> Word: MemCosine
        MOV     R7,R8,ASR #12
        MOV     R7,R7,LSL #BytesPerWordLog2
        LDR     R6,[R6,R7]

        MUL     R7,R4,R6
        MOV     R4,R7,ASR #12
        MUL     R7,R5,R6
        MOV     R5,R7,ASR #12
        ADD     R0,R0,R4,LSL #8
        ADD     R1,R1,R5,LSL #8

        LDR     R5,|SINE3|                  ; -> Word: MemSine
        MOV     R6,R8,ASR #12
        MOV     R6,R6,LSL #BytesPerWordLog2
        LDR     R5,[R5,R6]
        ADD     R2,R2,R5,LSL #8
        ADD     R3,R3,#QuarterTurn:SHL:AngleShift                   ; =&168000
        ADD     R3,R3,#HalfTurn:SHL:AngleShift                   ; =&2D0000
        CMP     R2,#TwoAndAHalfDegrees:SHL:AngleShift                      ; =&A000
        MOVLT   R2,#TwoAndAHalfDegrees:SHL:AngleShift                      ; =&A000

        LDR     R9,[R10,#PlayerRotationX]                  ; =492
        SUBS    R9,R9,#&05,18                   ; =&14000
        ADDMI   R9,R9,#FullRotation:SHL:AngleShift                   ; =&5A0000
        STR     R9,[R10,#PlayerRotationX]                  ; =492

        LDR     R6,[R10,#PlayerGhostPlane]                  ; =268
        ADD     R7,R6,#AircraftCoord                      ; =20
        STMIA   R7,{R0-R2}

        MOV     R2,R8
        MOV     R4,R9
        STMIA   R6,{R2-R4}

|L00005244|
        LDR     R0,[R10,#PlayerAircraftToView]                  ; =264
        CMP     R0,#&79                         ; ="y" (121)
        BNE     |L00005294|

        LDR     R2,[R10,#PlayerCameraPlane]                  ; =280
        LDR     R2,[R2,#AircraftTargetPtr]                   ; =172
        ADD     R2,R2,#AircraftCoord                      ; =20
        LDMIA   R2,{R2-R4}

        ADD     R4,R4,#&32000 ; increase AircraftCoordZ

        MOV     R2,R2,LSR #23
        MOV     R2,R2,LSL #23

        MOV     R3,R3,LSR #23
        MOV     R3,R3,LSL #23

        MOV     R4,R4,LSR #23
        MOV     R4,R4,LSL #23

        ADD     R2,R2,#&01,10                   ; =&400000
        ADD     R3,R3,#&01,10                   ; =&400000
        ADD     R4,R4,#&01,10                   ; =&400000

        LDR     R1,[R10,#PlayerCameraPlane]                  ; =280
        ADD     R1,R1,#AircraftCoord                      ; =20
        STMIA   R1,{R2-R4}
|L00005294|
        LDR     R0,[R10,#PlayerAircraftToView]                  ; =264
        CMP     R0,#&7A                         ; ="z" (122)
        BNE     |L000052E8|

        LDR     R2,[R10,#PlayerCameraPlane]                  ; =280
        LDR     R2,[R2,#AircraftTargetPtr]                   ; =172
        ADD     R2,R2,#AircraftCoord                      ; =20
        LDMIA   R2,{R2-R4}

        ADD     R4,R4,#&32000 ; increase AircraftCoordZ

        MOV     R2,R2,LSR #22
        MOV     R2,R2,LSL #22
        MOV     R3,R3,LSR #22
        MOV     R3,R3,LSL #22
        MOV     R4,R4,LSR #22
        MOV     R4,R4,LSL #22
        ADD     R2,R2,#&02,12                   ; =&200000
        ADD     R3,R3,#&02,12                   ; =&200000
        ADD     R4,R4,#&02,12                   ; =&200000
        ADD     R4,R4,#AircraftCentreZCoord            ; =&A000

        LDR     R1,[R10,#PlayerCameraPlane]                  ; =280
        ADD     R1,R1,#AircraftCoord                      ; =20
        STMIA   R1,{R2-R4}

|L000052E8|
        MOV     R0,#ReadKey                         ; ="" (129)
        LDR     R1,[R10,#PlayerKeyChangeCamDist]    ; =1<<8
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOCHANGECAMDIST|

        LDR     R1,[R10,#PlayerDebounceChangeCamDist]                  ; =312
        CMP     R1,#KeyIsPressed                ; ="" (255)
        BEQ     |NOCHANGECAMDIST|

        LDR     R0,[R10,#PlayerCamDistLog2]                  ; =276
        ADD     R0,R0,#1
        CMP     R0,#MaxCamDistLog2
        MOVEQ   R0,#0
        STR     R0,[R10,#PlayerCamDistLog2]                  ; =276

        STR     PC,|PREVENTTIMESKIP|                  ; -> Word: &00000000

        MOV     R1,#KeyIsPressed                ; ="" (255)
|NOCHANGECAMDIST|
        STR     R1,[R10,#PlayerDebounceChangeCamDist]                  ; =312

        MOV     R0,#ReadKey                         ; ="" (129)
        LDR     R1,[R10,#PlayerKeyResetView]                  ; =260
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NORESETVIEW|

|RESETVIEW|
        MOV     R0,#QuarterFront
        STR     R0,[R10,#AircraftViewQuarter]                  ; =36
        STR     R0,[R10,#AircraftViewAngle]                  ; =40

        MOV     R0,#ViewInside
        STR     R0,[R10,#AircraftViewIn]                  ; =44

        MOV     R0,#NumFramesFullFrontView
        STR     R0,|DRAWFULLFRONTVIEWCOUNT|                  ; -> Word: &00000000

        MOV     R3,R10
        STR     R3,[R10,#PlayerAircraftToViewPtr]                  ; =272

        STR     PC,|PREVENTTIMESKIP|                  ; -> Word: &00000000

        MOV     R0,#0
        STR     R0,[R10,#PlayerCamDistLog2]                  ; =276

        MOV     R0,#CamThisPlayer                         ; =20
        STR     R0,[R10,#PlayerAircraftToView]                  ; =264
        STR     R0,[R10,#PlayerAircraftToViewB]                  ; =496

        LDR     R0,[R10,#PlayerCameraPlane]                  ; =280
        STR     R10,[R0,#AircraftTargetPtr]                  ; =172

|NORESETVIEW|
        LDR     R0,|PSPLITSCREEN4|                  ; -> Word: &00016B28
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BNE     |NODETAIL4|

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#Key1                         ; ="0" (48)
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NODETAIL1|

        MOV     R0,#9
        STR     R0,|GRAPHICSDETAIL|                  ; -> Word: &0000000F

|NODETAIL1|
        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#Key2                         ; ="1" (49)
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NODETAIL2|

        MOV     R0,#&0C                         ; =12
        STR     R0,|GRAPHICSDETAIL|                  ; -> Word: &0000000F

|NODETAIL2|
        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#Key3                         ; =17
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NODETAIL3|

        MOV     R0,#&10                         ; =16
        STR     R0,|GRAPHICSDETAIL|                  ; -> Word: &0000000F

|NODETAIL3|
        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#Key4                         ; =18
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NODETAIL4|

        MOV     R0,#6
        STR     R0,|GRAPHICSDETAIL|                  ; -> Word: &0000000F

|NODETAIL4|
        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#Key5                         ; =19
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOTOGGLETHICK|

        LDR     R1,|LASTKEY5STATUS|                  ; -> Word: &00000000
        CMP     R1,#KeyIsPressed                ; ="" (255)
        BEQ     |NOTOGGLETHICK|

        LDR     R0,|PALLOWOUTLINEORTHICK|                  ; -> Word: &0001D1E4
        LDR     R1,[R0,#0]
        RSB     R1,R1,#1
        STR     R1,[R0,#0]

        MOV     R1,#KeyIsPressed                ; ="" (255)
|NOTOGGLETHICK|
        STR     R1,|LASTKEY5STATUS|                  ; -> Word: &00000000

        ; Override throttle setting if out of fuel
        LDR     R1,[R10,#AircraftFuel]                  ; =1<<6
        CMP     R1,#MinFuel                         ; =10
        MOVLT   R1,#0
        STRLT   R1,[R10,#AircraftThrottle]                  ; =48

        MOV     R0,R10 ; Player info
        MOV     R1,R11 ; AircraftCtrlX
        MOV     R2,R12 ; AircraftCtrlY
        LDR     R14,|RETFROMREADKEYS| ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|L00005478|
        DCD     |PLAYER1GHOST|
|PALLOWOUTLINEORTHICK|
        DCD     |ALLOWOUTLINEORTHICK|
|LASTKEY5STATUS|
        DCD     &00000000                       ; Word r/w (referenced)
        DCD     |PPLAYERINFO2|
        DCD     |MAXCLIPDIST|
        DCD     &00000000                       ;~ Word -/-
|PUNUSEDDIVIDENDA|
        DCD     |UNUSEDDIVIDENDA|
|PBULLETDIVIDENDA|
        DCD     |BULLETDIVIDENDA|
|PPUFFDIVIDENDA|
        DCD     |PUFFDIVIDENDA|
|PDEADDIVIDENDA|
        DCD     |DEADDIVIDENDA|
|PDIVIDENDSRC|
        DCD     |DIVIDENDSRC|
|DIVIDENDSRC|
        DCD     &0000927C                       ;~~~ Word -/-
        DCD     &000249F0                       ;~~ Word -/-
        DCD     &00124F80                       ;~~~ Word -/-
        DCD     &00927C00                       ;~~~ Word -/-
        DCD     |DRAWGAUGES|
        DCD     &000493E0                       ;~~~ Word -/-
        DCD     &00249F00                       ;~~~ Word -/-
        DCD     &0124F800                       ;~~~ Word -/-
|TMPREPLAYPLAYERINFO|
        DCD     &00000000                       ; Word r/w (referenced)
|TMPREPLAYCTRLX|
        DCD     &00000000                       ; Word r/w (referenced)
|TMPREPLAYCTRLY|
        DCD     &00000000                       ; Word r/w (referenced)
|RANDOMSEED|
        DCD     |RETFROMGAMESTART|
|TMPPLAYERPTR|
        DCD     &00000000                       ; Word r/w (referenced)
|PLAYERCTRLX|
        DCD     &00000000                       ; Word r/w (referenced)
|PLAYERCTRLY|
        DCD     &00000000                       ; Word r/w (referenced)
        DCD     |L000054E4|
|L000054E4|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     |CHEATACCUM|
        DCD     |L0000780C|
|MOUSECONFIG|
        DCD     &00000000                       ; Word r/- (referenced)
|PSPLITSCREEN4|
        DCD     |SPLITSCREEN|
        DCD     NumPracticeAircraft             ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
|AIRCRAFTDATAARRAY3|
        DCD     MemAircraftDataArray                       ; Word r/- (referenced)
|PPLAYERINFO8|
        DCD     |PLAYER1INFO|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     |L000009F0|
        DCD     &00000000                       ;~ Word -/-
|PPLAYER1INFO10|
        DCD     |PLAYER1INFO|
|PPLAYER2INFO9|
        DCD     |PLAYER2INFO|
        DCD     |PLAYER1GHOST|
        DCD     |PLAYER1GHOST|
|GRAPHICSDETAIL|
        DCD     &0000000F                       ; Word -/w (referenced)
|PCLIPDIST|
        DCD     |CLIPDIST|
|P2ENABLETARGETVIEW|
        DCD     |ENABLETARGETVIEW|
|P2PREVENTTIMESKIP|
        DCD     |PREVENTTIMESKIP|
        DCD     &00000000                       ;~ Word -/-
|PTARGETDATAARRAY5|
        DCD     MemTargetDataArray                       ; Word r/- (referenced)
|L00005554|
        DCD     |PLAYER1CAMERAPLANE|
|PPICMAP4|
        DCD     |PICMAP|

|INITDETAILNVIEW|
        LDR     R0,|P2ENABLETARGETVIEW|                  ; -> Word: &00011434, Function entry, (alters flags)
        LDR     R0,[R0,#0]
        CMP     R0,#0
        MOVEQ   R0,#9 ; not target view
        MOVNE   R0,#&14 ; target view
        STR     R0,|GRAPHICSDETAIL|                  ; -> Word: &0000000F

        LDR     R0,|PCLIPDIST|                  ; -> Word: &0001C82C
        MOVNE   R1,#&200 ; target view
        MOVEQ   R1,#&80 ; not target view
        STR     R1,[R0,#0]

        MOV     R1,#0 ; bug?
        STR     R1,[R0,#4] ; bug? set |UNUSEDCLIPDIST|

        LDR     R0,|PPICMAP4|                  ; -> Word: &00017258
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BEQ     |NOPICMAP|

        ; Set values for map picture
        MOV     R0,#&14                         ; =20
        STR     R0,|GRAPHICSDETAIL|                  ; -> Word: &0000000F

        LDR     R0,|PCLIPDIST|                  ; -> Word: &0001C82C
        MOV     R1,#&02,24                      ; =&200
        STR     R1,[R0,#0]

|NOPICMAP|
        LDR     R3,|DEMOSTATUS|                  ; -> Word: &00000000
        CMP     R3,#0
        LDR     R3,|PPLAYERINFO8|                  ; -> Word: &00019AA4
        LDRNE   R3,|L00005554|                  ; -> Word: &0001BD04

        LDR     R4,|PPLAYER1INFO10|                  ; -> Word: &00019AA4
        STR     R3,[R4,#PlayerAircraftToViewPtr]                   ; =272

        LDR     R5,|PPLAYER2INFO9|                  ; -> Word: &00019CB0
        STR     R5,[R5,#PlayerAircraftToViewPtr]                   ; =272

        LDR     R0,|P2PREVENTTIMESKIP|                  ; -> Word: &00015714
        STR     PC,[R0,#0]

        MOV     R0,#0
        STR     R0,[R4,#PlayerCamDistLog2]                   ; =276
        STR     R0,[R5,#PlayerCamDistLog2]                   ; =276

        MOV     R0,#&14                         ; =20
        MOVNE   R0,#&7A                         ; ="z" (122)
        STR     R0,[R4,#PlayerAircraftToView]                   ; =264
        STR     R0,[R5,#PlayerAircraftToView]                   ; =264

        LDR     R0,[R4,#PlayerCameraPlane]                   ; =280

        MOV     R1,#QuarterFront
        STR     R1,[R0,#AircraftViewQuarter]                   ; =36

        MOV     R2,#ViewInside
        STR     R2,[R0,#AircraftViewIn]                   ; =44

        LDR     R0,[R5,#PlayerCameraPlane]                   ; =280
        MOV     R1,#QuarterFront
        STR     R1,[R0,#AircraftViewQuarter]                   ; =36

        MOV     R2,#ViewInside
        STR     R2,[R0,#AircraftViewIn]                   ; =44

        LDR     R0,[R4,#PlayerGhostPlane]                   ; =268
        STR     R1,[R0,#AircraftViewQuarter]                   ; =36
        STR     R2,[R0,#AircraftViewIn]                   ; =44

        LDR     R0,[R5,#PlayerGhostPlane]                   ; =268
        STR     R1,[R0,#AircraftViewQuarter]                   ; =36
        STR     R2,[R0,#AircraftViewIn]                   ; =44

        LDR     R0,|PDIVIDENDSRC|                  ; -> Word: &00016614
        LDMIA   R0,{R0-R3}

        LDR     R4,|PUNUSEDDIVIDENDA|                  ; -> Word: &000122F0
        STMIA   R4,{R0-R3}

        LDR     R4,|PBULLETDIVIDENDA|                  ; -> Word: &00013328
        STMIA   R4,{R0-R3}

        LDR     R4,|PPUFFDIVIDENDA|                  ; -> Word: &000146B0
        STMIA   R4,{R0-R3}

        LDR     R4,|PDEADDIVIDENDA|                  ; -> Word: &0001F20C
        STMIA   R4,{R0-R3}

        MOV     R1,#&FF                         ; ="" (255)
        MOV     PC,R14                          ; Function exit, Ends

|MAPDRAWOFFSET|
        DCD     &00000000                       ; Word r/w (referenced)
|FRAMEBUFFER4|
        DCD     |FRAMEBUFFER|
|PPLAYERINFOCOPY|
        DCD     &00000000                       ; Word r/w (referenced)
|PMAXYCOORDY3|
        DCD     |MAXCOORDY3|

|DRAWMAP|
        ; R10 = playerinfo
        LDR     R9,[R10,#PlayerMapDrawOffset]                  ; =316, Function entry, (alters flags)
        STR     R9,|MAPDRAWOFFSET|                  ; -> Word: &00000000
        STR     R10,|PPLAYERINFOCOPY|                 ; -> Word: &00000000
        STR     R14,|RETFROMDRAWMAP|                 ; -> Word: &00000000

        LDR     R14,|SPLITSCREEN|                 ; -> Word: &00000001
        CMP     R14,#0
        MOVEQ   R14,#(HEIGHT-1)                        ; ="" (255)
        MOVNE   R14,#(SPLITHEIGHT-2)                        ; ="~" (126)
        LDR     R9,|PMAXYCOORDY3|                  ; -> Word: &00011430
        STR     R14,[R9,#0]

        BL      |INITDRAWINGFORMAP|

        LDR     R0,|FRAMEBUFFER5|                  ; -> Word: &0001204C
        LDR     R0,[R0,#0]
        LDR     R1,|MAPDRAWOFFSET|                  ; -> Word: &00000000
        ADD     R0,R0,R1
        LDR     R1,|BYTESPERFRAMEBUFFER|                  ; -> Word: &00014000
        ADD     R1,R1,R0

        LDR     R2,|PGROUNDFILLSRCADDR|         ; -> Word: &00011FCC
        LDR     R2,[R2,#0]
        LDMIA   R2,{R2-R12}

        LDR     R14,|SPLITSCREEN|                 ; -> Word: &00000001
        CMP     R14,#1
        SUBEQ   R1,R1,#128*RowStride               ; =&A000
        SUBEQ   R1,R1,#RowStride                   ; =&140

|CLEARMAPLOOP|
        STMIA   R0!,{R2-R11}
        STMIA   R0!,{R2-R11}
        STMIA   R0!,{R2-R11}
        STMIA   R0!,{R2-R11}
        STMIA   R0!,{R2-R11}
        STMIA   R0!,{R2-R11} ; 240 pixels
        CMP     R14,#1
        ADDEQ   R0,R0,#DASHBOARDWIDTH                      ; ="P" (80)
        STMNEIA R0!,{R2-R11}
        STMNEIA R0!,{R2-R11} ; 80 pixels
        CMP     R0,R1
        BLT     |CLEARMAPLOOP|

        LDR     R10,|MAPDRAWOFFSET|                 ; -> Word: &00000000
        LDR     R0,|FRAMEBUFFER5|                  ; -> Word: &0001204C
        LDR     R0,[R0,#0]
        ADD     R0,R0,R10
        LDR     R12,|SPLITSCREEN|                 ; -> Word: &00000001
        BL      |DRAWSCENERYONMAP|

        LDR     R0,|PPLAYERINFOCOPY|                  ; -> Word: &00000000
        LDR     R12,[R0,#AircraftHeading]
        LDR     R1,[R0,#AircraftType]                   ; =140
        CMP     R1,#ATYPE_CAMERA
        SUBEQ   R12,R12,#HalfTurn:SHL:AngleShift                 ; =&2D0000
        CMP     R12,#0
        ADDLT   R12,R12,#FullRotation:SHL:AngleShift                 ; =&5A0000

        ADD     R0,R0,#AircraftCoord                      ; =20
        LDMIA   R0,{R1,R2}

        LDR     R0,|SPLITSCREEN|                  ; -> Word: &00000001
        CMP     R0,#1
        MOV     R0,R1,ASR #19
        MVN     R1,R2,ASR #19
        MOVEQ   R0,R0,ASR #1
        MOVEQ   R1,R1,ASR #1

        MOV     R12,R12,ASR #AngleShift
        BIC     R12,R12,#AngleStepMask

        LDR     R8,|COSINE4|                  ; -> Word: MemCosine
        LDR     R9,|SINE4|                  ; -> Word: MemSine
        SUB     R12,R12,#QuarterTurn                 ; =&5A0
        CMP     R12,#0
        ADDLT   R12,R12,#FullRotation                 ; =&1680

        LDR     R8,[R8,R12]
        LDR     R9,[R9,R12]

        LDR     R2,|MAPDRAWOFFSET|                  ; -> Word: &00000000
        LDR     R3,|FRAMEBUFFER4|                  ; -> Word: &0001204C
        LDR     R4,[R3,#0]
        ADD     R4,R4,R2
        STR     R4,[R3,#0]

        ; Draw the player's heading and position as an arrow on the map
        SUB     R2,R0,R8,ASR #7
        ADD     R3,R1,R9,ASR #7

        LDR     R4,|CROSSHAIRCOLOURADDR|                  ; -> Word: &00018984
        LDR     R4,[R4,#0]

        STMFD   R13!,{R0-R12}
        BL      |DRAW2DLINE|
        LDMFD   R13!,{R0-R12}

        ADD     R2,R0,R8,ASR #7
        SUB     R3,R1,R9,ASR #7

        STMFD   R13!,{R0-R12}
        BL      |DRAW2DLINE|
        LDMFD   R13!,{R0-R12}

        MOV     R10,R0
        MOV     R11,R1
        ADD     R0,R10,R9,ASR #8
        ADD     R1,R11,R8,ASR #8

        STMFD   R13!,{R0-R12}
        BL      |DRAW2DLINE|
        LDMFD   R13!,{R0-R12}

        MOV     R6,R0
        MOV     R7,R1
        SUB     R0,R10,R9,ASR #8
        SUB     R1,R11,R8,ASR #8

        STMFD   R13!,{R0-R12}
        BL      |DRAW2DLINE|
        LDMFD   R13!,{R0-R12}

        MOV     R2,R6
        MOV     R3,R7
        BL      |DRAW2DLINE|

        LDR     R2,|MAPDRAWOFFSET|                  ; -> Word: &00000000
        LDR     R3,|FRAMEBUFFER4|                  ; -> Word: &0001204C
        LDR     R4,[R3,#0]
        SUB     R4,R4,R2
        STR     R4,[R3,#0]

        LDR     R0,|L00005960|                  ; -> Word: &00011FB8
        LDR     R0,[R0,#0]
        CMP     R0,#1
        BNE     |NOMORETARGETSONMAP|

        LDR     R0,|PMISSIONDATARRAY|                  ; -> Word: &00017CAC
        LDR     R1,|MISSIONNUM|                  ; -> Word: &00000001
        CMP     R1,#(MissionFirstRecon-1)        ; ="d" (100)
        BGE     |NOMORETARGETSONMAP|

        CMP     R1,#MissionFirstPractice                        ; =21
        MOVGE   R1,#MissionFirstPractice                        ; =21
        SUB     R1,R1,#1
        ADD     R0,R0,R1,LSL #BytesPerMissionLog2
        STR     R0,|PMISSIONDATA|                  ; -> Word: &00000000

        MOVNE   R11,#NumAircraft
        MOVGE   R11,#NumPracticeAircraft
|DRAWAIRCRAFTONMAPLOOP|
        LDR     R1,[R0,#0]
        ADD     R0,R0,#BytesPerAddress
        CMP     R1,#0
        BEQ     |NOMOREAIRCRAFTONMAP|

        LDR     R4,|SPLITSCREEN|                  ; -> Word: &00000001
        ADD     R4,R4,#&13                      ; =19
        LDR     R2,[R1,#AircraftDamage]                   ; =56
        CMP     R2,#DeadAircraftDamage                         ; =30
        LDRLT   R12,[R1,#AircraftType]                  ; =140
        LDRLT   R2,[R1,#AircraftCoordY]                   ; =24
        LDRLT   R1,[R1,#AircraftCoordX]                   ; =20
        MOVLT   R1,R1,ASR R4
        MVNLT   R2,R2,ASR R4
        ADDLT   R12,R12,#&32                    ; ="2" (50)
        BLLT    |DRAWBLOTONMAP|

        SUB     R11,R11,#1
        CMP     R11,#0
        BGT     |DRAWAIRCRAFTONMAPLOOP|

|NOMOREAIRCRAFTONMAP|
        LDR     R1,|MISSIONNUM|                  ; -> Word: &00000001
        CMP     R1,#MissionFirstPractice                        ; =21
        MOVGE   R1,#MissionFirstPractice; bug?                  ; =21

        LDR     R0,|PMISSIONDATA|                  ; -> Word: &00000000
        ADDNE   R0,R0,#&20                      ; =" " (32)
        ADDGE   R0,R0,#&50                      ; ="P" (80)
        MOVNE   R11,#NumTargets
        MOVGE   R11,#NumPracticeTargets
|DRAWTARGETONMAPLOOP|
        LDR     R1,[R0,#0]
        ADD     R0,R0,#BytesPerAddress
        CMP     R1,#0
        BEQ     |NOMORETARGETSONMAP|

        LDR     R4,|SPLITSCREEN|                  ; -> Word: &00000001
        ADD     R4,R4,#9
        LDR     R2,[R1,#TargetHitpoints]                   ; =28
        CMP     R2,#0
        LDRGE   R12,[R1,#TargetType]                  ; =24
        LDRGE   R2,[R1,#4]
        LDRGE   R1,[R1,#0]
        MVNGE   R1,R1,ASR R4
        MOVGE   R2,R2,ASR R4
        ADDGE   R12,R12,#NapierGreen                    ; ="d" (100)
        BLGE    |DRAWBLOTONMAP|

        SUB     R11,R11,#1
        CMP     R11,#0
        BGT     |DRAWTARGETONMAPLOOP|

|NOMORETARGETSONMAP|
        LDR     R0,|PPLAYERINFOCOPY|                  ; -> Word: &00000000
        LDR     R0,[R0,#PlayerOtherPlayerPtr]                   ; =304
        LDR     R1,[R0,#AircraftDamage]                   ; =56
        CMP     R1,#FatalAircraftDamage                         ; =11
        BGT     |NOWHITEBLOT|

        LDR     R1,|L00005960|                  ; -> Word: &00011FB8
        LDR     R1,[R1,#0]
        CMP     R1,#1
        BEQ     |NOWHITEBLOT|

        LDR     R9,|SPLITSCREEN|                  ; -> Word: &00000001
        CMP     R9,#0
        MOVEQ   R9,#&13                         ; =19
        MOVNE   R9,#&14                         ; =20

        ADD     R0,R0,#AircraftCoord                      ; =20
        LDMIA   R0,{R1,R2}
        MOV     R1,R1,ASR R9
        MVN     R2,R2,ASR R9
        MOV     R12,#White                        ; ="" (255)
        BL      |DRAWBLOTONMAP|

|NOWHITEBLOT|
        LDR     R14,|RETFROMDRAWMAP|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|PPLAYER2INFO10|
        DCD     |PLAYER2INFO|
|CROSSHAIRCOLOURADDR|
        DCD     |CROSSHAIRCOLOUR|
|L00005960|
        DCD     |COUNT0TO2|
|RETFROMDRAWMAP|
        DCD     &00000000                       ; Word r/w (referenced)
        DCD     &00000000                       ;~ Word -/-
        DCD     |L000011F0|
        DCD     |PVDUVARS|
        DCD     |MAXCOORDY4|
        DCD     |MAXCOORDY7|
        DCD     |MAXCOORDY8|
|FRAMEBUFFER5|
        DCD     |FRAMEBUFFER|
        DCD     |FRAMEBUFFER2|
        DCD     |FRAMEBUFFERCOPY|
|PGROUNDFILLSRCADDR|
        DCD     |GROUNDFILLSRCADDR|
|BYTESPERFRAMEBUFFER|
        DCD     RowStride*HEIGHT
|PPLAYERINFO9|
        DCD     |PLAYER1INFO|
        DCD     &00000000                       ;~ Word -/-
|COSINE4|
        DCD     MemCosine                       ; Word r/- (referenced)
|SINE4|
        DCD     MemSine                       ; Word r/- (referenced)
|SCREENLIMITSPTR|
        DCD     |MAXCOORDX3|
        DCD     |MAXCOORDY4|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     |AIRCRAFTTYPE|
|SPLITSCREEN|
        DCD     &00000001                       ; Word r/- (referenced)
|L000059BC|
        DCD     &00000000                       ;~ Word -/-

|DRAWBLOTONMAP|
        ; R1,R2 coords?
        ; R12 colour byte
        LDR     R4,|SCREENLIMITSPTR|                  ; -> Word: &0001142C, Function entry, (alters flags)
        LDR     R4,[R4,#0] ; xmax
        ADD     R1,R1,R4,LSL #(CoordToScreenLog2-1)
        MOV     R1,R1,ASR #CoordToScreenLog2
        SUB     R4,R4,#4
        CMP     R1,R4 ; x > xmax
        MOVGT   PC,R14                          ; Function exit if GT
        CMP     R1,#1
        MOVLT   PC,R14                          ; Function exit if LT

        LDR     R4,|SPLITSCREEN|                  ; -> Word: &00000001
        CMP     R4,#1
        MOVEQ   R4,#(SPLITHEIGHT-2)                         ; ="~" (126)
        MOVNE   R4,#(HEIGHT-2)                         ; ="" (254)
        ADD     R2,R2,R4,LSL #(CoordToScreenLog2-1)
        MOV     R2,R2,ASR #CoordToScreenLog2
        SUB     R4,R4,#1
        CMP     R2,R4 ; y > ymax
        MOVGT   PC,R14                          ; Function exit if GT
        CMP     R2,#1
        MOVLT   PC,R14                          ; Function exit if LT
        MOV     R3,#RowStride
        MUL     R4,R2,R3
        ADD     R4,R4,R1 ; (y * stride) + x
        LDR     R2,|FRAMEBUFFER5|                  ; -> Word: &0001204C
        LDR     R2,[R2,#0]
        LDR     R3,|MAPDRAWOFFSET|                  ; -> Word: &00000000
        ADD     R2,R2,R3
        ADD     R2,R2,R4
        STRB    R12,[R2,#0]
        STRB    R12,[R2,#1]
        STRB    R12,[R2,#-1]
        STRB    R12,[R2,#-RowStride]                 ; =&3FFFFFB<<6
        STRB    R12,[R2,#RowStride]                  ; =5<<6
        MOV     PC,R14                          ; Function exit, Ends

|SERVICEALLAIRCRAFT|
        STR     R14,|RETFROMSERVICEALLAIRCRAFT|                 ; -> Word: &00000000, Function entry, (alters flags)
        MOV     R0,#0
        STR     R0,|AIRCRAFTDATAARRAYOFFSET|                  ; -> Word: &00000000
|SERVICEAIRCRAFTLOOP|
        LDR     R12,|AIRCRAFTDATAARRAYCOPY|                 ; -> Word: &00000000
        LDR     R3,|AIRCRAFTDATAARRAYOFFSET|                  ; -> Word: &00000000
        ADD     R0,R12,R3
        BL      |SERVICEAIRCRAFT|

        LDR     R3,|AIRCRAFTDATAARRAYOFFSET|                  ; -> Word: &00000000
        ADD     R3,R3,#BytesPerAircraft                      ; ="" (184)
        STR     R3,|AIRCRAFTDATAARRAYOFFSET|                  ; -> Word: &00000000

        LDR     R4,|OFFSETTOENDOFAIRCRAFT|                  ; -> Word: &00000000
        CMP     R3,R4
        BLT     |SERVICEAIRCRAFTLOOP|

        LDR     R0,|P2PLAYER1CAMERAPLANE|                  ; -> Word: &0001BD04
        BL      |SERVICEAIRCRAFT|

        LDR     R0,|PSPLITSCREEN5|                  ; -> Word: &00016B28
        LDR     R0,[R0,#0]
        CMP     R0,#0
        LDREQ   R14,|RETFROMSERVICEALLAIRCRAFT|                 ; -> Word: &00000000
        MOVEQ   PC,R14                          ; Function exit if EQ

        ; Is serial game
        LDR     R0,|P2PLAYER2CAMERAPLANE|                  ; -> Word: &0001BDCC
        BL      |SERVICEAIRCRAFT|

        LDR     R14,|RETFROMSERVICEALLAIRCRAFT|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|RETFROMSERVICEALLAIRCRAFT|
        DCD     &00000000                       ; Word r/w (referenced)
|P2PLAYER1CAMERAPLANE|
        DCD     |PLAYER1CAMERAPLANE|
|PSPLITSCREEN5|
        DCD     |SPLITSCREEN|
|P2PLAYER2CAMERAPLANE|
        DCD     |PLAYER2CAMERAPLANE|
|AIRCRAFTDATAARRAYOFFSET|
        DCD     &00000000                       ; Word r/w (referenced)
|AIRCRAFTDATAARRAYCOPY|
        DCD     &00000000                       ; Word r/- (referenced)
|OFFSETTOENDOFAIRCRAFT|
        DCD     &00000000                       ; Word r/- (referenced)
        DCD     |MISSIONNUM|
|DOGFIGHT|
        DCD     &00000000                       ; Word r/- (referenced)
|STARTFROMCARRIER|
        DCD     &00000000                       ; Word r/- (referenced)
|RECONPIC|
        DCD     |L000047E8|
|MASTERSTATUS2|
        DCD     |SERIALISMASTER|
|PNUMPLAYERS2|
        DCD     |NUMPLAYERS|

|INITGAME|
        STR     R14,|RETFROMINITGAMEORSVCMISSION|                 ; -> Word: &00000000, Function entry, (alters flags)
        LDR     R1,|RECONPIC|                  ; -> Word: &00015958
        MOV     R0,#0
        STR     R0,[R1,#0]

        BL      |INITDETAILNVIEW|

        LDR     R0,|AIRCRAFTDATAARRAYCOPY|                  ; -> Word: &00000000
        MOV     R12,#0
|INITAIRCRAFTARRAYLOOP|
        ADD     R1,R0,R12 ; dest address
        ADD     R2,R1,#AircraftBackup ; source address         ; ="D" (68)
        MOV     R14,R1
        LDMIA   R2!,{R3-R11}
        STMIA   R1!,{R3-R11}
        LDMIA   R2!,{R3-R10}
        STMIA   R1!,{R3-R10}

        LDR     R3,[R14,#AircraftViewMap]                  ; =168
        CMP     R3,#&15,26                      ; =&540
        MOVGT   R3,#&15,26                      ; =&540
        STRGT   R3,[R14,#AircraftViewMap]       ; =168

        MOV     R3,#0
        STR     R3,[R14,#AircraftMsgRemain]                  ; =176
        STR     R3,[R14,#AircraftMsgNum]                  ; =180
        STR     R3,[R14,#AircraftTargetDist]                  ; =136
        STR     R3,[R14,#AircraftViewAngle]                  ; =40

        LDR     R3,|MASTERSTATUS2|                  ; -> Word: &0001BE9C
        LDR     R3,[R3,#0]
        CMP     R3,#0
        LDREQ   R3,|PPLAYER1INFO12|                  ; -> Word: &00019AA4
        LDRNE   R3,|PPLAYER2INFO11|                  ; -> Word: &00019CB0
        STR     R3,[R14,#AircraftTargetPtr]                  ; =172

        ADD     R12,R12,#BytesPerAircraft                    ; ="" (184)
        LDR     R3,|OFFSETTOENDOFAIRCRAFT|                  ; -> Word: &00000000
        CMP     R12,R3
        BLT     |INITAIRCRAFTARRAYLOOP|

        LDR     R0,|PTARGETDATAARRAY2|                  ; -> Word: &0001462C
        LDR     R0,[R0,#0]
        MOV     R1,#NumPracticeTargets  ; =20
        MOV     R2,#TTYPE_GUN_BOAT  ; bug: unused
|INITHITPOINTSLOOP|
        LDR     R2,[R0,#TargetType]                   ; =24
        MOV     R3,#&0A                         ; =10
        CMP     R2,#TTYPE_AIRSHIP
        MOVEQ   R3,#&1E                         ; =30

        CMP     R2,#TTYPE_GROUND_GUN_BASE
        MOVEQ   R3,#3

        CMP     R2,#TTYPE_TANK
        MOVEQ   R3,#4

        CMP     R2,#TTYPE_TRAIN
        MOVEQ   R3,#&14                         ; =20

        CMP     R2,#TTYPE_GUN_BOAT
        MOVEQ   R3,#&19                         ; =25

        CMP     R2,#TTYPE_OIL_TANKER
        MOVEQ   R3,#&2D                         ; ="-" (45)

        CMP     R2,#TTYPE_GOTHA_G_IV_BOMBER
        MOVEQ   R3,#&0F                         ; =15

        CMP     R2,#TTYPE_FOKKER_EINDECKER_IV
        CMPNE   R2,#TTYPE_FOKKER_V7_TWIN
        CMPNE   R2,#TTYPE_FOKKER_V3_TRIENGINE
        MOVEQ   R3,#5

        CMP     R2,#TTYPE_CARGO_AIRCRAFT
        MOVEQ   R3,#&12                         ; =18

        CMP     R2,#TTYPE_YACHT
        MOVEQ   R3,#3

        CMP     R2,#TTYPE_RAILWAY_STATION
        MOVEQ   R3,#&1E                         ; =30

        CMP     R2,#TTYPE_BRIDGE
        MOVEQ   R3,#&32                         ; ="2" (50)

        CMP     R2,#TTYPE_FACTORY
        MOVEQ   R3,#&28                         ; ="(" (40)

        CMP     R2,#TTYPE_AIRCRAFT_CARRIER
        MOVEQ   R3,#&64                         ; ="d" (100)

        STR     R3,[R0,#TargetHitpoints]                   ; =28

        ADD     R0,R0,#1:SHL:BytesPerTargetLog2                     ; =" " (32)
        SUB     R1,R1,#1
        CMP     R1,#0
        BGT     |INITHITPOINTSLOOP|

        ; Decide player's starting height
        LDR     R12,|STARTFROMCARRIER|                 ; -> Word: &00000000
        CMP     R12,#1
        MOVEQ   R12,#CarrierDeckZCoord                  ; =&64000
        MOVNE   R12,#0
        ADD     R12,R12,#AircraftCentreZCoord              ; =&A000

        LDR     R0,|PPLAYER1INFO12|                  ; -> Word: &00019AA4
        MOV     R2,R0

        LDR     R3,|MASTERSTATUS2|                  ; -> Word: &0001BE9C
        LDR     R3,[R3,#0]
        CMP     R3,#1
        LDREQ   R2,|PPLAYER2INFO11|                  ; -> Word: &00019CB0

        ADD     R2,R2,#AircraftBackup                      ; ="D" (68)

        LDR     R3,|PICMAP|                  ; -> Word: &00000000
        CMP     R3,#0
        LDRNE   R2,|PPICMAPAIRCRAFTPRESETS|                  ; -> Word: &0001BCC0

        LDMIA   R2!,{R3-R11}
        MOV     R10,R12 ; player start height
        STMIA   R0!,{R3-R11} ; store x,y,z angles,?,?, x,y,z coordinates
        LDMIA   R2!,{R3-R10}
        STMIA   R0!,{R3-R10}

        LDR     R0,|PPLAYER2INFO11|                  ; -> Word: &00019CB0
        MOV     R2,R0

        LDR     R3,|MASTERSTATUS2|                  ; -> Word: &0001BE9C
        LDR     R3,[R3,#0]
        CMP     R3,#1
        LDREQ   R2,|PPLAYER1INFO12|                  ; -> Word: &00019AA4

        ADD     R2,R2,#AircraftBackup                      ; ="D" (68)

        LDMIA   R2!,{R3-R11}
        MOV     R10,R12
        STMIA   R0!,{R3-R11}
        LDMIA   R2!,{R3-R10}
        STMIA   R0!,{R3-R10}

        LDR     R12,|STARTFROMCARRIER|                 ; -> Word: &00000000
        CMP     R12,#1
        MOV     R12,#AircraftCentreZCoord              ; =&A000
        ADDEQ   R12,R12,#CarrierDeckZCoord           ; =&64000

        LDR     R0,|PPLAYER2INFO11|                  ; -> Word: &00019CB0
        STR     R12,[R0,#PlayerMinZCoord]                  ; =184

        LDR     R0,|PPLAYER1INFO12|                  ; -> Word: &00019AA4
        STR     R12,[R0,#PlayerMinZCoord]                  ; =184

        LDR     R0,|DOGFIGHT|                  ; -> Word: &00000000
        CMP     R0,#0
        BEQ     |INITNODOGFIGHT|

        LDR     R1,|MASTERSTATUS2|                  ; -> Word: &0001BE9C
        LDR     R1,[R1,#0]
        CMP     R1,#1
        LDR     R0,|PPLAYER2INFO11|                  ; -> Word: &00019CB0
        LDREQ   R0,|PPLAYER1INFO12|                  ; -> Word: &00019AA4

        MOV     R1,#&05,10                      ; =&1400000
        ADD     R1,R1,#&02,12                   ; =&200000
        STR     R1,[R0,#AircraftCoordX]                   ; =20

        LDR     R0,|PPLAYER1INFO12|                  ; -> Word: &00019AA4
        LDREQ   R0,|PPLAYER2INFO11|                  ; -> Word: &00019CB0
        RSB     R1,R1,#0
        STR     R1,[R0,#AircraftCoordX]                   ; =20

        MOV     R1,#QuarterTurn:SHL:AngleShift                      ; =&168000
        STR     R1,[R0,#AircraftHeading]
|INITNODOGFIGHT|
        LDR     R0,|PNUMPLAYERS2|                  ; -> Word: &0001A03C
        LDR     R0,[R0,#0]
        CMP     R0,#1
        BNE     |INITMULTIPLAYER|

        LDR     R0,|PPLAYER2INFO11|                  ; -> Word: &00019CB0
        MOV     R1,#DeadAircraftDamage                         ; =30
        STR     R1,[R0,#AircraftDamage]                   ; =56

|INITMULTIPLAYER|
        LDR     R0,|PPLAYER1INFO12|                  ; -> Word: &00019AA4
        LDR     R1,|PPLAYER2INFO11|                  ; -> Word: &00019CB0
        MOV     R2,#0
        MOV     R3,#0
        MOV     R4,#0

        ADD     R0,R0,#(AircraftCoordCopy-AircraftCoord)   ; ="" (136)
        STMIA   R0!,{R2-R4} ; zero 36 bytes
        STMIA   R0!,{R2-R4}
        STMIA   R0!,{R2-R4}

        ADD     R1,R1,#(AircraftCoordCopy-AircraftCoord)   ; ="" (136)
        STMIA   R1!,{R2-R4} ; zero 36 bytes
        STMIA   R1!,{R2-R4}
        STMIA   R1!,{R2-R4}

        LDR     R0,|PMISSIONNUM3|                  ; -> Word: &000177B8
        LDR     R0,[R0,#0]
        CMP     R0,#&0A                         ; =10
        BNE     |L00005DC4|

        LDR     R0,|PPLAYER1INFO12|                  ; -> Word: &00019AA4
        MOV     R1,#&02,12                      ; =&200000
        MOV     R2,#&01,16                      ; =&10000
        MOV     R3,#&3C                         ; ="<" (60)
        STR     R1,[R0,#AircraftCoordZ]                   ; =28
        STR     R3,[R0,#AircraftThrottle]                   ; =48
        STR     R2,[R0,#AircraftSpeed]                   ; =16

        LDR     R4,[R0,#AircraftCoordX]                   ; =20
        ADD     R4,R4,#&01,4                    ; =&10000000
        STR     R4,[R0,#AircraftCoordX]                   ; =20

        LDR     R0,|PPLAYER2INFO11|                  ; -> Word: &00019CB0
        STR     R1,[R0,#AircraftCoordZ]                   ; =28
        STR     R3,[R0,#AircraftThrottle]                   ; =48
        STR     R2,[R0,#AircraftSpeed]                   ; =16

        LDR     R4,[R0,#AircraftCoordX]                   ; =20
        ADD     R4,R4,#&01,4                    ; =&10000000
        STR     R4,[R0,#AircraftCoordX]                   ; =20

        LDR     R0,|PPLAYER1GHOST|                  ; -> Word: &00019EBC
        STR     R1,[R0,#AircraftCoordZ]                   ; =28
        STR     R3,[R0,#AircraftThrottle]                   ; =48
        STR     R2,[R0,#AircraftSpeed]                   ; =16

        LDR     R4,[R0,#AircraftCoordX]                   ; =20
        ADD     R4,R4,#&01,4                    ; =&10000000
        STR     R4,[R0,#AircraftCoordX]                   ; =20

        LDR     R0,|PPLAYER1GHOSTB|                  ; -> Word: &00019EBC
        STR     R1,[R0,#AircraftCoordZ]                   ; =28
        STR     R3,[R0,#AircraftThrottle]                   ; =48
        STR     R2,[R0,#AircraftSpeed]                   ; =16

        LDR     R4,[R0,#AircraftCoordX]                   ; =20
        ADD     R4,R4,#&01,4                    ; =&10000000
        STR     R4,[R0,#AircraftCoordX]                   ; =20
|L00005DC4|
        MOV     R1,#0
        LDR     R0,|PPLAYER1INFO12|                  ; -> Word: &00019AA4
        STR     R1,[R0,#AircraftCtrlX]                   ; =144
        STR     R1,[R0,#AircraftCtrlY]                   ; =148
        LDR     R0,|PPLAYER2INFO11|                  ; -> Word: &00019CB0
        STR     R1,[R0,#AircraftCtrlX]                   ; =144
        STR     R1,[R0,#AircraftCtrlY]                   ; =148
        LDR     R0,|PPLAYER1GHOST|                  ; -> Word: &00019EBC
        STR     R1,[R0,#AircraftCtrlX]                   ; =144
        STR     R1,[R0,#AircraftCtrlY]                   ; =148
        LDR     R0,|PPLAYER1GHOSTB|                  ; -> Word: &00019EBC
        STR     R1,[R0,#AircraftCtrlX]                   ; =144
        STR     R1,[R0,#AircraftCtrlY]                   ; =148
        BL      |CLEARPLAYERBULLETSARRAY|
        BL      |CLEARPUFFARRAY|
        BL      |CLEARENEMYBULLETARRAY|
        BL      |CLEAREXPLOSIONOUTPUT|

        LDR     R0,|PDRAWFULLFRONTVIEWCOUNT|                  ; -> Word: &00016268
        MOV     R1,#2
        STR     R1,[R0,#0]

        LDR     R0,|SCREENBANKNUMADDR|                  ; -> Word: &0001155C
        MOV     R1,#0
        STR     R1,[R0,#0]

        MOV     R3,#AircraftCentreZCoord               ; =&A000
        LDR     R0,|PTAKEOFFALTITUDE|                  ; -> Word: &0001A310

        LDR     R1,|PMISSIONNUM3|                  ; -> Word: &000177B8
        LDR     R1,[R1,#0] ; bug: r1 is unused

        LDR     R1,|STARTFROMCARRIER|                  ; -> Word: &00000000
        CMP     R1,#1
        BNE     |NOTCARRIERSTART|

        LDR     R4,|CARRIERDECKHEIGHT|                  ; -> Word: &00064000
        ADD     R3,R3,R4

|NOTCARRIERSTART|
        STR     R3,[R0,#0] ; store TAKEOFFALTITUDE

        SUB     R3,R3,#AircraftCentreZCoord            ; =&A000
        LDR     R0,|PDECKORGROUNDLEVEL|                  ; -> Word: &00012834
        STR     R3,[R0,#0]

        LDR     R0,|PPLAYER1INFO12|                  ; -> Word: &00019AA4
        MOVNV   R0,R0                           ; CAUTION: not 32bit safe (uses NV).
        MOV     R0,#ChannelGun
        MOV     R1,#VoiceGun
        SWI     Sound_AttachVoice

        MOV     R0,#ChannelEngine1
        MOV     R1,#VoiceEngine
        SWI     Sound_AttachVoice

        MOV     R0,#ChannelEngine2
        MOV     R1,#VoiceEngine
        SWI     Sound_AttachVoice

        LDR     R1,|PSYSTIME|                  ; -> Word: &00017244
        MOV     R0,#0
        STR     R0,[R1,#0]
        STR     R0,[R1,#4]
        MOV     R0,#WriteSystemClock
        SWI     OS_Word

        LDR     R0,|P2UNKNOWN|                  ; -> Word: &00018E48
        MOV     R1,#0
        STR     R1,[R0,#0]

        LDR     R2,|PICMAP|                  ; -> Word: &00000000
        CMP     R2,#0
        BEQ     |NOPICMAP2|

        ; Set aircraft coordinates for map picture
        LDR     R0,|PPLAYER1INFO12|                  ; -> Word: &00019AA4
        SUB     R2,R2,#1
        LDR     R1,|PPICMAPCOORDS|                  ; -> Word: &00019764
        ADD     R1,R1,R2,LSL #4
        LDMIA   R1,{R2-R4} ; Get AircraftCoordX, AircraftCoordY, AircraftCoordZ
        ADD     R0,R0,#AircraftCoord                      ; =20
        STMIA   R0,{R2-R4}

        LDR     R0,|PDRAWFULLFRONTVIEWCOUNT|                  ; -> Word: &00016268
        MOV     R1,#0
        STR     R1,[R0,#0]

|NOPICMAP2|
        LDR     R0,|L000060DC|                  ; -> Word: &0001897C
        MOV     R1,#1
        STR     R1,[R0,#0]
        LDR     R0,|HITLIST3|                  ; -> Word: MemHitList
        MOV     R1,#&14                         ; =20
        MOV     R2,#0
|CLEARHITLISTLOOP|
        STR     R2,[R0,#0]
        ADD     R0,R0,#4
        SUBS    R1,R1,#1
        BPL     |CLEARHITLISTLOOP|

        LDR     R0,|L000060E0|                  ; -> Word: &00013340
        MOV     R1,#0
        STR     R1,[R0,#0]

        LDR     R0,|P3PREVENTTIMESKIP|                  ; -> Word: &00015714
        STR     PC,[R0,#0]

        MOV     R1,#0
        LDR     R0,|OLDCAMPOSB|                  ; -> Word: &0001D9D4
        STR     R1,[R0,#0] ; x = 0
        STR     R1,[R0,#4] ; y = 0

        LDR     R0,|PPLAYER1INFO12|                  ; -> Word: &00019AA4
        LDR     R1,|PPLAYER2INFO11|                  ; -> Word: &00019CB0
        LDR     R2,|PPLAYER1GHOSTC|                  ; -> Word: &00019EBC
        LDR     R3,|PPLAYER2GHOST|                  ; -> Word: &00019F7C
        STR     R2,[R0,#PlayerGhostPlane]                   ; =268
        STR     R3,[R1,#PlayerGhostPlane]                   ; =268

        LDR     R2,|PPLAYER1CAMERAPLANE|                  ; -> Word: &0001BD04
        LDR     R3,|PPLAYER2CAMERAPLANE|                  ; -> Word: &0001BDCC
        STR     R2,[R0,#PlayerCameraPlane]                   ; =280
        STR     R3,[R1,#PlayerCameraPlane]                   ; =280

        ; Player 1 has a pointer to player 2 and vice versa
        STR     R1,[R0,#PlayerOtherPlayerPtr]                   ; =304
        STR     R0,[R1,#PlayerOtherPlayerPtr]                   ; =304

        MOV     R2,#0
        STR     R2,[R0,#PlayerMapDrawOffset]                   ; =316

        LDR     R2,|SCREENOFFSET2|                  ; -> Word: &0000A050
        STR     R2,[R1,#PlayerMapDrawOffset]                   ; =316

        LDR     R2,|PSPLITSCREEN6|                  ; -> Word: &00016B28
        LDR     R2,[R2,#0]
        CMP     R2,#0

        ; Test position for single-player game
        MOVEQ   R2,#5  ; PlayerMessageCoordX (single player)
        MOVEQ   R3,#10 ; PlayerMessageCoordY
        MOVEQ   R4,#5  ; ?
        MOVEQ   R5,#2  ; ?

        ; Test position for player 1 split screen
        MOVNE   R2,#0 ; PlayerMessageCoordX (two player)
        MOVNE   R3,#5 ; PlayerMessageCoordY
        MOVNE   R4,#0
        MOVNE   R5,#2

        ; Initialize text position for player 1
        ADD     R6,R0,#PlayerMessageCoord            ; =&140
        STMIA   R6,{R2-R5}

        ; Test position for player 2 split screen
        MOV     R2,#&0A                         ; =10
        MOV     R3,#&15                         ; =21
        MOV     R4,#&0A                         ; =10
        MOV     R5,#&12                         ; =18

        ; Initialize text position for player 2
        ADD     R6,R1,#PlayerMessageCoord            ; =&140
        STMIA   R6,{R2-R5}

        ; Two-player gauge values
        ; PlayerSpeedoX, PlayerSpeedoY
        MOV     R2,#8
        MOV     R3,#4
        ; PlayerAltimX, PlayerAltimY
        MOV     R4,#&A4                         ; ="" (164)
        MOV     R5,#4
        ; PlayerAltimShortX, PlayerAltimShortY
        MOV     R6,#&A4                         ; ="" (164)
        MOV     R7,#4
        ; PlayerCompassX, PlayerCompassY
        MOV     R8,#&99                         ; ="" (153)
        MOV     R9,#&A1                         ; ="" (161)
        ; PlayerFuelGaugeX, PlayerFuelGaugeY
        MOV     R10,#&0B                        ; =11
        MOV     R11,#&B1                        ; ="" (177)

        LDR     R12,|PSPLITSCREEN6|                 ; -> Word: &00016B28
        LDR     R12,[R12,#0]
        CMP     R12,#0
        BNE     |NOSINGLEPLAYERGAUGEINIT|

        ; Single-player gauge values
        ; PlayerSpeedoX, PlayerSpeedoY
        MVN     R2,#&46                         ; ="F" (70)
        MOV     R3,#&1A,28                      ; =&1A0
        ; PlayerAltimX, PlayerAltimY
        MOV     R4,#&46                         ; ="F" (70)
        MOV     R5,#&1B,28                      ; =&1B0
        ; PlayerAltimShortX, PlayerAltimShortY
        MOV     R6,#&46                         ; ="F" (70)
        MOV     R7,#&1B,28                      ; =&1B0
        ; PlayerCompassX, PlayerCompassY
        MOV     R8,#&C8                         ; ="" (200)
        MOV     R9,#&71,30                      ; =&1C4
        ; PlayerFuelGaugeX, PlayerFuelGaugeY
        MVN     R10,#&C8                        ; ="" (200)
        MOV     R11,#&75,30                     ; =&1D4

|NOSINGLEPLAYERGAUGEINIT|
        ; Initialize gauge states for player 1
        ADD     R12,R0,#PlayerSpeedoX       ; =&150
        STMIA   R12!,{R2,R3} ; PlayerSpeedoX, PlayerSpeedoY
        STMIA   R12!,{R2,R3} ; PlayerSpeedoOldX, PlayerSpeedoOldY
        STMIA   R12!,{R4,R5} ; PlayerAltimX, PlayerAltimY
        STMIA   R12!,{R4,R5} ; PlayerAltimOldX, PlayerAltimOldY
        STMIA   R12!,{R6,R7} ; PlayerAltimShortX, PlayerAltimShortY
        STMIA   R12!,{R6,R7} ; PlayerAltimShortOldX, PlayerAltimShortOldY
        STMIA   R12!,{R8,R9} ; PlayerCompassX, PlayerCompassY
        STMIA   R12!,{R8,R9} ; PlayerCompassOldX, PlayerCompassOldY
        STMIA   R12!,{R10,R11} ; PlayerFuelGaugeX, PlayerFuelGaugeY
        STMIA   R12!,{R10,R11} ; PlayerFuelGaugeOldX, PlayerFuelGaugeOldY
        STMIA   R12!,{R2-R11} ; PlayerSpeedoOrigX..PlayerFuelGaugeOrigY

        ; Initialize gauge states for player 2
        ADD     R12,R1,#PlayerSpeedoX         ; =&150
        STMIA   R12!,{R2,R3}
        STMIA   R12!,{R2,R3}
        STMIA   R12!,{R4,R5}
        STMIA   R12!,{R4,R5}
        STMIA   R12!,{R6,R7}
        STMIA   R12!,{R6,R7}
        STMIA   R12!,{R8,R9}
        STMIA   R12!,{R8,R9}
        STMIA   R12!,{R10,R11}
        STMIA   R12!,{R10,R11}
        STMIA   R12!,{R2-R11}

        LDR     R14,|RETFROMINITGAMEORSVCMISSION|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|RETFROMINITGAMEORSVCMISSION|
        DCD     &00000000                       ; Word r/w (referenced)
|PTARGETDATAARRAY2|
        DCD     |TARGETDATAARRAY|
|PPLAYER1INFO12|
        DCD     |PLAYER1INFO|
|PDRAWFULLFRONTVIEWCOUNT|
        DCD     |DRAWFULLFRONTVIEWCOUNT|
        DCD     |UNKNOWN2|
|SCREENBANKNUMADDR|
        DCD     |FRAMEBUFFERNUM|
        DCD     |ISPRACTICEMISSION|
|PMISSIONNUM3|
        DCD     |MISSIONNUM|
|PTAKEOFFALTITUDE|
        DCD     |TAKEOFFALTITUDE|
|CARRIERDECKHEIGHT|
        DCD     CarrierDeckZCoord                       ; Word r/- (referenced)
|PDECKORGROUNDLEVEL|
        DCD     |DECKORGROUNDLEVEL|
|PSYSTIME|
        DCD     |SYSTIME|
|P2UNKNOWN|
        DCD     |UNKNOWN|
|PPICMAPAIRCRAFTPRESETS|
        DCD     |PICMAPAIRCRAFTPRESETS|
|P3PREVENTTIMESKIP|
        DCD     |PREVENTTIMESKIP|
|OLDCAMPOSB|
        DCD     |L0000C864|
|PPLAYER2INFO11|
        DCD     |PLAYER2INFO|
|PPLAYER1GHOST|
        DCD     |PLAYER1GHOST|
|PPLAYER1GHOSTB|
        DCD     |PLAYER1GHOST|
|PPLAYER1GHOSTC|
        DCD     |PLAYER1GHOST|
|PPLAYER2GHOST|
        DCD     |PLAYER2GHOST|
|PPLAYER1CAMERAPLANE|
        DCD     |PLAYER1CAMERAPLANE|
|PPLAYER2CAMERAPLANE|
        DCD     |PLAYER2CAMERAPLANE|
|SYSTIME|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
|L000060DC|
        DCD     |L0000780C|
|L000060E0|
        DCD     |SMOKEGENOFFSET|
|PSPLITSCREEN6|
        DCD     |SPLITSCREEN|
|PICMAP|
        DCD     &00000000                       ; Word r/- (referenced)
|PPICMAPCOORDS|
        DCD     |PICMAPCOORDS|
|HITLIST3|
        DCD     MemHitList                       ; Word r/- (referenced)
|SCREENOFFSET2|
        DCD     (RowStride*SPLITHEIGHT)+DASHBOARDWIDTH    ; Word r/- (referenced)

|DOENGINESOUND|
        STMFD   R13!,{R0-R4}                    ; Function entry, (alters flags)
        LDR     R1,|PSYSTIME|                  ; -> Word: &00017244
        MOV     R0,#ReadSystemClock
        SWI     OS_Word

        LDR     R2,[R1,#0]
        CMP     R2,#EngineSoundInterleavePeriodCS
        BGT     |SWITCHENGINESOUNDCHANNEL|

|KEEPENGINESOUNDCHANNEL|
        CMP     R2,#EngineSoundRepeatPeriodCS
        BLT     |NOENGINESOUND|

        MOV     R2,#0
        STR     R2,[R1,#0]
        STR     R2,[R1,#4]
        MOV     R0,#WriteSystemClock
        SWI     OS_Word

        ; Set up to do engine sound for player 1
        LDR     R0,|PPLAYER1INFO13|                  ; -> Word: &00019AA4
        STR     R0,|ENGINESOUNDPLAYERINFO|            ; -> Word: &00019AA4

        MOV     R0,#0
        STR     R0,|ENGINESOUNDCHANNEL|              ; -> Word: &00000000

|ENGINESOUNDCHANNELCHOSEN|
        LDR     R0,|ENGINESOUNDPLAYERINFO|  ; -> Word: &00019AA4
        LDR     R0,[R0,#PlayerAircraftToViewPtr]                   ; =272
        LDR     R1,[R0,#AircraftSpeed]                   ; =16
        MOV     R1,R1,ASR #SpeedToEnginePitchLog2

        LDR     R2,[R0,#AircraftType]                   ; =140
        CMP     R2,#ATYPE_JET_FIGHTER
        BEQ     |NOENGINESOUND|

        LDR     R2,[R0,#AircraftThrottle]                   ; =48
        CMP     R2,#0
        BEQ     |NOENGINESOUND|

        MOV     R2,R2,LSL #ThrottleToEnginePitchLog2
        ADD     R2,R2,R1 ; and speed

        LDR     R1,|ENGINESOUNDPLAYERINFO|                  ; -> Word: &00019AA4
        LDR     R1,[R1,#PlayerAircraftToView]                   ; =264
        CMP     R1,#CamTarget                         ; ="d" (100)
        BLT     |CHOOSEINSIDEOROUTSIDEVOL|

        CMP     R1,#CamGhost                         ; ="{" (123)
        BEQ     |CHOOSEINSIDEOROUTSIDEVOL|

        LDR     R0,|ENGINESOUNDPLAYERINFO|                  ; -> Word: &00019AA4
        LDR     R1,[R0,#AircraftSpeed]                   ; =16
        MOV     R1,R1,ASR #SpeedToEnginePitchLog2

        LDR     R2,[R0,#AircraftThrottle]                   ; =48
        CMP     R2,#0
        BEQ     |NOENGINESOUND|

        MOV     R2,R2,LSL #ThrottleToEnginePitchLog2
        ADD     R2,R2,R1 ; and speed

        LDR     R0,|ENGINESOUNDPLAYERINFO|                  ; -> Word: &00019AA4
        LDR     R0,[R0,#PlayerAircraftToViewPtr]                   ; =272
        LDR     R0,[R0,#AircraftTargetDist]                   ; =136
        CMP     R0,#MinRangeFixedEngineVolume        ; ="P" (80)
        MVN     R1,#4
        BGE     |MAKESOUND| ; too far away to scale (quiet) engine noise

        MOV     R0,R0,ASR #3 ; scale range to target
        RSB     R0,R0,#9
        SUB     R1,R1,R0 ; shorter range means louder
        B       |MAKESOUND|                     ; Ends

|CHOOSEINSIDEOROUTSIDEVOL|
        ; R2 = pitch
        LDR     R1,[R0,#AircraftViewIn]                   ; =44
        CMP     R1,#ViewInside
        MVNEQ   R1,#EngineInsideVolume    ; =10
        MVNNE   R1,#EngineOutsideVolume   ; =12

|MAKESOUND|
        LDR     R0,|ENGINESOUNDCHANNEL|                  ; -> Word: &00000000
        CMP     R0,#0
        MOVEQ   R0,#ChannelEngine1
        MOVNE   R0,#ChannelEngine2
        MOV     R3,#&0A                         ; =10
        SWI     Sound_Control

|NOENGINESOUND|
        LDMFD   R13!,{R0-R4}
        MOV     PC,R14                          ; Function exit, Ends

|PPLAYER1INFO13|
        DCD     |PLAYER1INFO|
|PPLAYER2INFO12|
        DCD     |PLAYER2INFO|
|ENGINESOUNDCHANNEL|
        DCD     &00000000                       ; Word r/w (referenced)
|PSPLITSCREEN7|
        DCD     |SPLITSCREEN|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
|ENGINESOUNDPLAYERINFO|
        DCD     |PLAYER1INFO|

|SWITCHENGINESOUNDCHANNEL|
        LDR     R0,|PSPLITSCREEN7|                  ; -> Word: &00016B28
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BEQ     |KEEPENGINESOUNDCHANNEL|

        LDR     R0,|ENGINESOUNDCHANNEL|                  ; -> Word: &00000000
        CMP     R0,#0
        BNE     |KEEPENGINESOUNDCHANNEL|

        ; Set up to do engine sound for player 2
        MOV     R0,#1
        STR     R0,|ENGINESOUNDCHANNEL|                  ; -> Word: &00000000

        LDR     R0,|PPLAYER2INFO12|                  ; -> Word: &00019CB0
        STR     R0,|ENGINESOUNDPLAYERINFO|                  ; -> Word: &00019AA4

        B       |ENGINESOUNDCHANNELCHOSEN|                     ; Ends

|UPDATETARGETVIEW|
        MOV     R2,#&01,12                      ; =&100000, Function entry, (alters flags)
        STR     R2,|VIEWTARGETCOORDZ|                  ; -> Word: &00032000

        MOV     R0,#MESH_AVOCADO_FIELD               ; =">" (62)
        LDR     R1,|POBJARRAY|                  ; -> Word: MemObjArray
        STR     R0,[R1,#ObjMesh]

        MOV     R0,#0
        STR     R0,|COUNTUP|                  ; -> Word: &00000000

        LDR     R12,|VIEWDATANUM|                 ; -> Word: &00011438
        LDR     R12,[R12,#0]

        LDR     R0,|PVIEWTARGETCOORDS|                  ; -> Word: &0001758C
        LDMIA   R0,{R1-R3}

        LDR     R0,|PPLAYERINFO10|                  ; -> Word: &00019AA4
        CMP     R12,#MeshToTargetView              ; ="d" (100)
        BGE     |NOTPLANETARGETVIEW|

        ADD     R1,R1,#&01,14                   ; =&40000
        CMP     R12,#ATYPE_FOKKER_V7_TWIN
        CMPNE   R12,#ATYPE_FOKKER_V3_TRIENGINE
        ADDEQ   R1,R1,#&01,14                   ; =&40000

        CMP     R12,#ATYPE_GOTHA_G_IV_BOMBER
        ADDEQ   R1,R1,#&03,14                   ; =&C0000

        CMP     R12,#ATYPE_CARGO_AIRCRAFT
        ADDEQ   R1,R1,#&01,12                   ; =&100000

|NOTPLANETARGETVIEW|
        ADD     R0,R0,#AircraftCoord                      ; =20
        STMIA   R0,{R1-R3}
        MOV     PC,R14                          ; Function exit, Ends

|VIEWTARGET|
        STR     R14,|RETFROMVIEWTARGET|                 ; -> Word: &00000000, Function entry, (alters flags)
        LDR     R12,|VIEWDATANUM|                 ; -> Word: &00011438
        LDR     R12,[R12,#0]
        CMP     R12,#MeshToTargetView             ; ="d" (100)
        BGE     |VIEWNOPLANE|

        LDR     R0,|PVIEWTARGETCOORDS|                  ; -> Word: &0001758C
        LDMIA   R0,{R1-R6} ; get coordinates and angles

        ADD     R4,R4,#ViewAircraftRotStepX
        CMP     R4,#FullRotation                      ; =&1680
        SUBGT   R4,R4,#FullRotation                   ; =&1680

        ADD     R5,R5,#ViewAircraftRotStepY
        CMP     R5,#FullRotation                      ; =&1680
        SUBGT   R5,R5,#FullRotation                   ; =&1680

        ADD     R6,R6,#ViewAircraftRotStepZ
        CMP     R6,#FullRotation                      ; =&1680
        SUBGT   R6,R6,#FullRotation                   ; =&1680

        STMIA   R0,{R1-R6} ; store coordinates and updated angles

        LDR     R0,|P2AIRCRAFTCOORDS|                  ; -> Word: &00012A98
        STMIA   R0,{R1-R6} ; store coordinates and updated angles
        BL      |DRAWAIRCRAFT|

        LDR     R0,|COUNTUP|                  ; -> Word: &00000000
        ADD     R0,R0,#1
        STR     R0,|COUNTUP|                  ; -> Word: &00000000
        CMP     R0,#&0A                         ; =10
        BLT     |DORETFROMVIEWTARGET|

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeySpacebar
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BEQ     |EXITGAME|

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#&49                         ; ="I" (73)
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BEQ     |EXITGAME|

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyT
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BEQ     |EXITGAME|

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyEnter                         ; ="<" (60)
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BEQ     |EXITGAME|

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyP
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |L000063C8|
|WAITFORKEYLOOP|
        MOV     R0,#0
        STR     R0,|COUNTUP|                  ; -> Word: &00000000

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeySpacebar
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BEQ     |DORETFROMVIEWTARGET|

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyReturn
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BEQ     |DORETFROMVIEWTARGET|

        B       |WAITFORKEYLOOP|                     ; Ends
|L000063C8|
        BL      |READJSBUT|
        LDR     R0,|JSBUT0|                  ; -> Word: &00000000
        CMP     R0,#0
        BNE     |EXITGAME|

        SWI     OS_Mouse
        CMP     R2,#0 ; any button
        BNE     |EXITGAME|

|DORETFROMVIEWTARGET|
        LDR     R14,|RETFROMVIEWTARGET|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|RETFROMVIEWTARGET|
        DCD     &00000000                       ; Word r/w (referenced)
|PPLAYERINFO10|
        DCD     |PLAYER1INFO|
|P2AIRCRAFTCOORDS|
        DCD     |AIRCRAFTCOORDS|
|PVIEWTARGETCOORDS|
        DCD     |VIEWTARGETCOORDS|
|VIEWDATANUM|
        DCD     |L000002C8|
        DCD     |VIEWNOPLANE|
        DCD     |L000011EC|
|VIEWTARGETROT|
        DCD     &00000000                       ; Word r/w (referenced)
|COSINE5|
        DCD     MemCosine                       ; Word r/- (referenced)
|SINE5|
        DCD     MemSine                       ; Word r/- (referenced)
|P2STATICAIRCRAFTDATA|
        DCD     |STATICAIRCRAFTDATA|
|COUNTUP|
        DCD     &00000000                       ; Word r/w (referenced)
|VIEWTARGETCOORDS|
|VIEWTARGETCOORDX|
        DCD     &3D090000                       ; Word r/- (referenced)
        DCD     &00000000                       ;~ Word -/-
|VIEWTARGETCOORDZ|
        DCD     &00032000                       ; Word -/w (referenced)
; Angles of rotation below
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
|POBJARRAY|
        DCD     MemObjArray                       ; Word r/- (referenced)

|VIEWNOPLANE|
        ; R12 = target number (>=100)
        LDR     R0,|COUNTUP|                  ; -> Word: &00000000
        ADD     R0,R0,#1
        STR     R0,|COUNTUP|                  ; -> Word: &00000000
        CMP     R0,#&0A                         ; =10
        BLT     |VIEWNOPLANE2|

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyP
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NOPAUSE|

|WAITFORKEY|
        MOV     R0,#0
        STR     R0,|COUNTUP|                  ; -> Word: &00000000

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeySpacebar
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BEQ     |VIEWNOPLANE2|

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyReturn
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BEQ     |VIEWNOPLANE2|

        B       |WAITFORKEY|                     ; Ends
|NOPAUSE|
        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeySpacebar
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BEQ     |EXITGAME|

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyReturn
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BEQ     |EXITGAME|

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyEnter
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BEQ     |EXITGAME|

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyT
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BEQ     |EXITGAME|

        BL      |READJSBUT|
        LDR     R0,|JSBUT0|                  ; -> Word: &00000000
        CMP     R0,#0
        BNE     |EXITGAME|

        SWI     OS_Mouse
        CMP     R2,#0 ; any button
        BNE     |EXITGAME|

|VIEWNOPLANE2|
        ; R12 = target number (>=100)
        ; Convert to object mesh number
        SUB     R12,R12,#MeshToTargetView               ; ="d" (100)
        MOV     R11,R12

        CMP     R11,#TTYPE_AIRSHIP
        MOVEQ   R11,#MESH_AIRSHIP                        ; ="H" (72)

        CMP     R11,#TTYPE_BARRAGE_BALLOON
        MOVEQ   R11,#MESH_BARRAGE_BALLOON                        ; ="I" (73)

        CMP     R11,#TTYPE_CONTROL_TERMINAL
        MOVEQ   R11,#MESH_CONTROL_TERMINAL                        ; ="N" (78)

        CMP     R11,#TTYPE_OIL_TANKER
        MOVEQ   R11,#MESH_OIL_TANKER                        ; ="O" (79)

        CMP     R11,#TTYPE_GUN_BOAT
        MOVEQ   R11,#MESH_GUN_BOAT                        ; ="Q" (81)

        CMP     R11,#TTYPE_TRAIN
        MOVEQ   R11,#MESH_TRAIN                        ; ="U" (85)

        LDR     R0,|POBJARRAY|                  ; -> Word: MemObjArray
        STR     R11,[R0,#ObjMesh]

        LDR     R0,|VIEWTARGETROT|                  ; -> Word: &00000000
        LDR     R1,|COSINE5|                  ; -> Word: MemCosine
        LDR     R2,|SINE5|                  ; -> Word: MemSine
        LDR     R3,|P2STATICAIRCRAFTDATA|                  ; -> Word: &00012328
        ADD     R0,R0,#ViewTargetRotStep
        CMP     R0,#FullRotation                      ; =&1680
        SUBGT   R0,R0,#FullRotation                   ; =&1680
        STR     R0,|VIEWTARGETROT|                  ; -> Word: &00000000

        LDR     R10,[R1,R0] ; get cosine
        LDR     R11,[R2,R0] ; get sine
        LDR     R8,|VIEWTARGETCOORDX|                  ; -> Word: &3D090000
        MOV     R9,#0 ; default y coord
        ADD     R8,R8,R11,LSL #7
        ADD     R9,R9,R10,LSL #7
        ADD     R8,R8,R11,LSL #6
        ADD     R9,R9,R10,LSL #6

        CMP     R12,#TTYPE_AIRSHIP
        ADDEQ   R8,R8,R11,LSL #10
        ADDEQ   R9,R9,R10,LSL #11

        CMP     R12,#TTYPE_BARRAGE_BALLOON
        ADDEQ   R8,R8,R11,LSL #10
        ADDEQ   R9,R9,R10,LSL #10

        CMP     R12,#TTYPE_CONTROL_TERMINAL
        ADDEQ   R8,R8,R11,LSL #8
        ADDEQ   R9,R9,R10,LSL #8

        CMP     R12,#TTYPE_OIL_TANKER
        ADDEQ   R8,R8,R11,LSL #10
        ADDEQ   R9,R9,R10,LSL #11

        CMP     R12,#TTYPE_GUN_BOAT
        ADDEQ   R8,R8,R11,LSL #7
        ADDEQ   R9,R9,R10,LSL #8

        CMP     R12,#TTYPE_TRAIN
        ADDEQ   R8,R8,R11,LSL #7
        ADDEQ   R9,R9,R10,LSL #8

        MOV     R10,#AircraftCoordZDefault  ; =&30000

        CMP     R12,#TTYPE_AIRSHIP
        CMPNE   R12,#TTYPE_BARRAGE_BALLOON
        MOV     R7,#0 ; default ObjCoordZ
        MOVEQ   R10,#AircraftCoordZAirship  ; =&400000
        MVNEQ   R7,#(ObjCoordZAirship-1)             ; =&1000

        CMP     R12,#TTYPE_CONTROL_TERMINAL
        MOVEQ   R10,#AircraftCoordZTerminal  ; =&80000

        CMP     R12,#TTYPE_BARRAGE_BALLOON
        MOVEQ   R10,#AircraftCoordZBalloon   ; =&200000

        CMP     R12,#TTYPE_OIL_TANKER
        MOVEQ   R10,#AircraftCoordZTanker   ; =&200000

        CMP     R12,#TTYPE_GUN_BOAT
        MOVEQ   R10,#AircraftCoordZGunBoat   ; =&80000

        LDR     R1,|POBJARRAY|                  ; -> Word: MemObjArray
        STR     R7,[R1,#ObjCoordZ]                   ; =20

        LDR     R4,|PPLAYERINFO10|                  ; -> Word: &00019AA4
        ; Invert |VIEWTARGETROT|
        RSB     R0,R0,#FullRotation                   ; =&1680
        MOV     R0,R0,LSL #10
        STR     R0,[R4,#AircraftHeading]
        STR     R0,[R3,#AircraftHeading]

        ADD     R4,R4,#AircraftCoord                      ; =20
        STMIA   R4,{R8-R10} ; store aircraft coordinates

        LDR     R14,|RETFROMVIEWTARGET|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|MISSIONNUM|
        DCD     &00000001                       ; Word r/- (referenced)
|RECONPIC2|
        DCD     |L000047E8|
|PDOGFIGHT3|
        DCD     |DOGFIGHT|
|PMISSIONDATARRAY|
        DCD     |MISSIONDATAARRAY|
|PPLAYERINFO13|
        DCD     |PLAYER1INFO|
|PMISSIONDATA|
        DCD     &00000000                       ; Word r/w (referenced)
|P2OUTPUT|
        DCD     |OUTPUT|
|PPLAYER2INFO13|
        DCD     |PLAYER2INFO|
|PSTARTFROMCARRIER2|
        DCD     |STARTFROMCARRIER|

|CHECKCARRIERLANDING|
; r0 = aircraft pointer
; r1,r2,r3 coordinates
; r12 = aircraft height
        LDR     R9,|PSTARTFROMCARRIER2|                  ; -> Word: &00016C3C, Function entry, (alters flags)
        LDR     R9,[R9,#0]
        CMP     R9,#1
        MOVNE   PC,R14                          ; Function exit if NE

        ; Must be within the length of the ship
        MOV     R9,R1 ; x coordinate
        XABS    R9
        CMP     R9,#CarrierMainDeckMinMaxX
        BGT     |NOTONCARRIER|

        ; Must be within the (off-centre) beam width of the ship
        CMP     R2,#CarrierMainDeckMinMaxY ; y coordinate
        BGT     |NOTONCARRIER|

        CMN     R2,#CarrierSideDeckMinY ; y coordinate
        BLT     |NOTONCARRIER|

        ; Landed on the main deck?
        CMN     R2,#CarrierMainDeckMinMaxY ; y coordinate
        BGT     |ONCARRIER| ; yes

        ; Landed on the side deck? (shorter than the ship)
        CMN     R1,#CarrierSideDeckMinX ; x coordinate
        BLT     |NOTONCARRIER|

        CMP     R1,#CarrierSideDeckMaxX ; x coordinate
        BGT     |NOTONCARRIER|

|ONCARRIER|
        LDR     R9,[R0,#AircraftDamage]                   ; =56
        CMP     R9,#FatalAircraftDamage                         ; =11
        MOVEQ   R9,#CrashDamage                 ; =13
        STREQ   R9,[R0,#AircraftDamage]                   ; =56

        LDR     R9,|PLANEALTONCARRIER|                  ; -> Word: &0006E000
        CMP     R3,R9 ; compare with aircraft altitude
        BGT     |TOOHIGHFORCARRIERLANDING|

        CMP     R10,#&01,16                     ; =&10000
        MOVGT   R5,#OutputCrashLand
        BGT     |LANDINGISACRASH|

        STR     R14,|TMPRETURNADDR|                 ; -> Word: &00000000
        BL      |CHECKLANDING|
        LDR     R14,|TMPRETURNADDR|                 ; -> Word: &00000000

        MOV     R10,#CarrierDeckZCoord          ; =&64000
        SUB     R10,R10,#&01,16                 ; =&10000
        CMP     R3,R10
        MOVLT   R5,#OutputCrashLand
        BLT     |LANDINGISACRASH|

        MOV     R9,R3
        LDR     R11,|PLANEALTONCARRIER|                 ; -> Word: &0006E000
        CMP     R9,R11
        MOVLT   R3,R11

        LDR     R9,|P2TAKEOFFALTITUDE|                  ; -> Word: &0001A310
        STR     R11,[R9,#0]
        STR     R11,[R0,#PlayerMinZCoord]                  ; =184

        LDR     R9,|P2DECKORGROUNDLEVEL|        ; -> Word: &00012834
        MVN     R10,#&19,28                     ; =&190
        STR     R10,[R9,#0]

        ADD     R11,R11,#&01,24                 ; =&100
        CMP     R12,R11 ; check aircraft height above carrier deck
        BLE     |TOOHIGHFORCARRIERLANDING|

        STMFD   R13!,{R0-R12}

        MOV     R0,#ChannelMisc
        MOV     R1,#VoiceWheel
        SWI     Sound_AttachVoice

        MOV     R0,#ChannelMisc
        MVN     R1,#MaxVolume
        MOV     R2,#WheelPitch                      ; =&1800
        MOV     R3,#0
        SWI     Sound_Control

        LDMFD   R13!,{R0-R12}
        MOV     R8,R14 ; preserve return address
        STMFD   R13!,{R0-R12}

        ADD     R0,R0,#AircraftCoord                      ; =20
        LDMIA   R0,{R2,R3}
        MOV     R4,#CarrierDeckZCoord             ; =&64000
        MOV     R5,#SmokeTypeQuickBlack
        BL      |ADDSMOKEGEN|

        MOV     R14,R8 ; restore return address
        LDMFD   R13!,{R0-R12}
|TOOHIGHFORCARRIERLANDING|
        MOV     PC,R14                          ; Function exit, Ends

|NOTONCARRIER|
        LDR     R9,|P2TAKEOFFALTITUDE|                  ; -> Word: &0001A310
        LDR     R12,|AIRCRAFTCENTREZCOORD|                 ; -> Word: &0000A000
        STR     R12,[R9,#0]
        STR     R12,[R0,#PlayerMinZCoord]                  ; =184

        LDR     R9,|P2DECKORGROUNDLEVEL|                  ; -> Word: &00012834
        MOV     R12,#0
        STR     R12,[R9,#0]

        MOV     PC,R14                          ; Function exit, Ends

|RUNINFO|
        DCD     &0002DB0C                       ; Word r/- (referenced)
|NUMRUNWAYS|
        DCD     &00000000                       ; Word r/- (referenced)
        DCD     &00000000                       ;~ Word -/-

|CHECKRUNWAYLANDING|
        ; r1,r2,r3 coordinates
        CMP     R3,#AircraftCentreZCoord               ; =&A000, Function entry, (alters flags)
        STR     R14,|TMPRETURNADDR|                 ; -> Word: &00000000
        BLLT    |CHECKLANDING|
        LDR     R14,|TMPRETURNADDR|                 ; -> Word: &00000000

        LDR     R9,[R0,#AircraftDamage]                   ; =56
        CMP     R9,#FatalAircraftDamage                         ; =11
        MOVEQ   R9,#CrashDamage2                         ; =15
        STREQ   R9,[R0,#AircraftDamage]                   ; =56

        LDR     R8,|PSTARTFROMCARRIER2|                  ; -> Word: &00016C3C
        LDR     R8,[R8,#0]
        MOV     R8,#0

        CMP     R8,#1 ; bug: never happens
        MOVEQ   R3,#CrashDamage2                         ; =15
        STREQ   R3,[R0,#AircraftDamage]                   ; =56
        MOVEQ   R3,#AircraftCentreZCoord               ; =&A000
        MOVEQ   PC,R14                          ; Function exit if EQ

        ADD     R8,R0,#AircraftCoord                      ; =20
        LDMIA   R8,{R8,R9} ; get aircraft x and y
        CMP     R10,#&01,16                     ; =&10000
        MOVGT   R5,#OutputCrashLand
        BGT     |LANDINGISACRASH|

        STMFD   R13!,{R0-R12}
        LDR     R0,|RUNINFO|                  ; -> Word: &0002DB0C
        LDR     R1,|NUMRUNWAYS|                  ; -> Word: &00000000
|CHECKLANDONRUNWAYLOOP|
        LDMIA   R0!,{R2-R5}

        XABSDIFF R2,R2,R8
        XABSDIFF R3,R3,R9

        CMP     R2,R4
        CMPLT   R3,R5
        BLT     |LANDEDONRUNWAY|

        SUBS    R1,R1,#1
        BPL     |CHECKLANDONRUNWAYLOOP|

        B       |LANDEDOFFRUNWAY|                     ; Ends

|LANDEDONRUNWAY|
        LDMFD   R13!,{R0-R12}

        MOV     R10,#AircraftCentreZCoord              ; =&A000
        ADD     R10,R10,#&01,24                 ; =&100
        CMP     R12,R10
        BLE     |PERFECTLANDING|

        STMFD   R13!,{R0-R12}

        MOV     R0,#ChannelMisc
        MOV     R1,#VoiceWheel
        SWI     Sound_AttachVoice

        MOV     R0,#ChannelMisc
        MVN     R1,#MaxVolume
        MOV     R2,#WheelPitch                      ; =&1800
        MOV     R3,#0
        SWI     Sound_Control

        LDMFD   R13!,{R0-R12}
        MOV     R8,R14
        STMFD   R13!,{R0-R12}
        ADD     R0,R0,#AircraftCoord                      ; =20
        LDMIA   R0,{R2,R3}
        MOV     R4,#RunwayZCoord
        MOV     R5,#SmokeTypeQuickBlack
        BL      |ADDSMOKEGEN|

        MOV     R14,R8
        LDMFD   R13!,{R0-R12}
|PERFECTLANDING|
        MOV     R3,#AircraftCentreZCoord               ; =&A000
        MOV     PC,R14                          ; Function exit, Ends

|LANDEDOFFRUNWAY|
        LDMFD   R13!,{R0-R12}
        MOV     R5,#OutputBadLanding

|LANDINGISACRASH|
        STR     R5,|OUTPUT|                  ; -> Word: &00000000

        LDR     R6,[R0,#AircraftDamage]                   ; =56
        CMP     R6,#FatalAircraftDamage                         ; =11
        MOVGT   PC,R14                          ; Function exit if GT

        MOV     R6,#CrashDamage2                         ; =15
        STRLT   R6,[R0,#AircraftDamage]                   ; =56

        MOV     PC,R14                          ; Function exit, Ends

|P5OUTPUT|
        DCD     |OUTPUT|
|PPLAYERINFO11|
        DCD     |PLAYER1INFO|
|PLANEALTONCARRIER|
        DCD     CarrierDeckZCoord+AircraftCentreZCoord    ; Word r/- (referenced)
        DCD     |MISSIONNUM|
|P2TAKEOFFALTITUDE|
        DCD     |TAKEOFFALTITUDE|
|AIRCRAFTCENTREZCOORD|
        DCD     AircraftCentreZCoord        ; Word r/- (referenced)
|P2DECKORGROUNDLEVEL|
        DCD     |DECKORGROUNDLEVEL|
|OUTPUT|
        DCD     &00000000                       ; Word -/w (referenced)
|PPLAYERINFO12|
        DCD     |PLAYER1INFO|
        DCD     |AIRCRAFTTYPE|

|CHECKLANDING|
        STMFD   R13!,{R0-R12}                   ; Function entry, (alters flags)
        LDR     R1,[R0,#AircraftType]                   ; =140
        CMP     R1,#ATYPE_CAMERA
        BEQ     |PLAYER2LANDING|

        LDR     R2,[R0,#AircraftRoll]
        CMP     R2,#HalfTurn:SHL:AngleShift                      ; =&2D0000
        SUBGT   R2,R2,#FullRotation:SHL:AngleShift                   ; =&5A0000
        ABS     R2
        CMP     R2,#&31,20                      ; =&31000
        LDMGTFD R13!,{R0-R12}
        MOVGT   R5,#OutputBadLanding
        BGT     |LANDINGISACRASH|

        B       |RETFROMCHECKLANDING|                     ; Ends

|PLAYER2LANDING|
        LDR     R2,[R0,#AircraftRoll]
        SUB     R2,R2,#HalfTurn:SHL:AngleShift                   ; =&2D0000
        ABS     R2
        CMP     R2,#&31,20                      ; =&31000
        LDMGTFD R13!,{R0-R12}
        MOVGT   R5,#OutputBadLanding
        BGT     |LANDINGISACRASH|

|RETFROMCHECKLANDING|
        LDMFD   R13!,{R0-R12}
        MOV     PC,R14                          ; Function exit, Ends

|TMPRETURNADDR|
        DCD     &00000000                       ; Word r/w (referenced)

|SERVICEMISSION|
        STR     R14,|RETFROMINITGAMEORSVCMISSION|                 ; -> Word: &00000000, Function entry, (alters flags)
        LDR     R0,|PDOGFIGHT3|                  ; -> Word: &00016C38
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BNE     |ISDOGFIGHT3|

        LDR     R0,|MISSIONTIMER|                  ; -> Word: &00000000
        ADD     R0,R0,#1
        STR     R0,|MISSIONTIMER|                  ; -> Word: &00000000

        LDR     R0,|MISSIONNUM|                  ; -> Word: &00000001
        SUB     R2,R0,#1
        CMP     R0,#MissionFirstNoTargets        ; ="2" (50)
        BLT     |CHECKANYTARGETSALIVE|

        LDR     R1,|RECONPIC2|                  ; -> Word: &00015958
        LDR     R1,[R1,#0]
        CMP     R1,#0
        BNE     |CHECKFORMISSIONCOMPLETE|

        LDR     R14,|RETFROMINITGAMEORSVCMISSION|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|CHECKANYTARGETSALIVE|
        ; r2 = mission no. - 1
        LDR     R1,|PMISSIONDATARRAY|                  ; -> Word: &00017CAC
        ADD     R1,R1,R2,LSL #BytesPerMissionLog2
        STR     R1,|PMISSIONDATA|                  ; -> Word: &00000000

        MOV     R12,#NumAircraft
        MOV     R11,#0
|CHECKFORLIVEAIRCRAFTLOOP|
        LDR     R2,[R1,#0]
        ADD     R1,R1,#BytesPerAddress ; next aircraft
        CMP     R2,#0
        BEQ     |NOMOREAIRCRAFTALIVE|

        LDR     R3,[R2,#AircraftDamage]                   ; =56
        CMP     R3,#DeadAircraftDamage                         ; =30
        MOVLT   R11,#1 ; found a live one

        SUB     R12,R12,#1
        CMP     R12,#0
        BGT     |CHECKFORLIVEAIRCRAFTLOOP|

|NOMOREAIRCRAFTALIVE|
        MOV     R12,#NumTargets
        LDR     R1,|PMISSIONDATA|                  ; -> Word: &00000000
        ADD     R1,R1,#&20                      ; =" " (32)
|CHECKFORLIVETARGETSLOOP|
        LDR     R2,[R1,#0]
        ADD     R1,R1,#BytesPerAddress ; next target
        CMP     R2,#0
        BEQ     |NOMORETARGETSALIVE|

        LDR     R3,[R2,#TargetHitpoints]                   ; =28
        CMP     R3,#0
        MOVGE   R11,#1 ; found a live one

        SUB     R12,R12,#1
        CMP     R12,#0
        BGT     |CHECKFORLIVETARGETSLOOP|

|NOMORETARGETSALIVE|
        CMP     R11,#0
        BEQ     |CHECKFORMISSIONCOMPLETE| ; all targets are dead

        LDR     R14,|RETFROMINITGAMEORSVCMISSION|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|CHECKFORMISSIONCOMPLETE|
        LDR     R0,|PPLAYERINFO13|                  ; -> Word: &00019AA4
        LDR     R2,|PPLAYER2INFO13|                  ; -> Word: &00019CB0

        LDR     R1,[R0,#AircraftDamage]                   ; =56
        CMP     R1,#FatalAircraftDamage                   ; =11
        LDR     R1,[R2,#AircraftDamage]                   ; =56
        CMPGE   R1,#FatalAircraftDamage                   ; =11
        LDRGE   R14,|RETFROMINITGAMEORSVCMISSION|                 ; -> Word: &00000000
        MOVGE   PC,R14                          ; Function exit if GE

        ; Pick whichever player is still alive
        LDR     R1,[R0,#AircraftDamage]                   ; =56
        CMP     R1,#FatalAircraftDamage                   ; =11
        MOVGT   R0,R2 ; p1 is dead

        LDR     R1,[R2,#AircraftDamage]                   ; =56
        CMP     R1,#FatalAircraftDamage                   ; =11
        MOVGT   R2,R0 ; p2 is dead

        LDR     R1,[R0,#AircraftSpeed]                   ; =16
        CMP     R1,#MaxSpeedMissionComplete              ; =10
        LDRGT   R14,|RETFROMINITGAMEORSVCMISSION|                 ; -> Word: &00000000
        MOVGT   PC,R14                          ; Function exit if GT

        LDR     R1,[R2,#AircraftSpeed]                   ; =16
        CMP     R1,#MaxSpeedMissionComplete              ; =10
        LDRGT   R14,|RETFROMINITGAMEORSVCMISSION|                 ; -> Word: &00000000
        MOVGT   PC,R14                          ; Function exit if GT

        LDR     R1,[R0,#AircraftCoordX]                   ; =20
        ABS     R1
        CMP     R1,#&05,10                      ; =&1400000
        LDRGT   R14,|RETFROMINITGAMEORSVCMISSION|                 ; -> Word: &00000000
        MOVGT   PC,R14                          ; Function exit if GT

        LDR     R1,[R2,#AircraftCoordX]                   ; =20
        ABS     R1
        CMP     R1,#&05,10                      ; =&1400000
        LDRGT   R14,|RETFROMINITGAMEORSVCMISSION|                 ; -> Word: &00000000
        MOVGT   PC,R14                          ; Function exit if GT

        LDR     R1,[R0,#AircraftCoordY]                   ; =24
        ABS     R1
        CMP     R1,#&05,10                      ; =&1400000
        LDRGT   R14,|RETFROMINITGAMEORSVCMISSION|                 ; -> Word: &00000000
        MOVGT   PC,R14                          ; Function exit if GT

        LDR     R1,[R2,#AircraftCoordY]                   ; =24
        ABS     R1
        CMP     R1,#&05,10                      ; =&1400000
        LDRGT   R14,|RETFROMINITGAMEORSVCMISSION|                 ; -> Word: &00000000
        MOVGT   PC,R14                          ; Function exit if GT

        LDR     R1,[R0,#AircraftScore]                   ; =60

        ; The quicker the mission was finished, the better
        LDR     R2,|MISSIONTIMER|                  ; -> Word: &00000000
        RSBS    R2,R2,#&02,18                   ; =&8000
        MOVMI   R2,#0
        ADD     R1,R1,R2,ASR #8 ; add up to 128 to the score

        ; The less damage received, the better
        LDR     R2,[R0,#AircraftDamage]                   ; =56
        RSBS    R2,R2,#(FatalAircraftDamage-1)                   ; =10
        MOVMI   R2,#0
        ADD     R1,R1,R2,LSL #3 ; add up to 80 to the score

        STR     R1,[R0,#AircraftScore]                   ; =60

        LDR     R0,|P2OUTPUT|                  ; -> Word: &00017A54
        MOV     R1,#OutputMissionComplete
        STR     R1,[R0,#0]

        B       |EXITGAME|                     ; Ends

|ISDOGFIGHT3|
        LDR     R0,|PPLAYERINFO13|                  ; -> Word: &00019AA4
        LDR     R2,|PPLAYER2INFO13|                  ; -> Word: &00019CB0
        LDR     R0,[R0,#AircraftDamage]                   ; =56
        LDR     R2,[R2,#AircraftDamage]                   ; =56
        CMP     R0,#&20                         ; =" " (32)
        CMPLT   R2,#&20                         ; =" " (32)
        MOVLT   PC,R14                          ; Function exit if LT

        LDR     R0,|P2OUTPUT|                  ; -> Word: &00017A54
        MOV     R1,#OutputMissionComplete
        STR     R1,[R0,#0]

        B       |EXITGAME|                     ; Ends

|MISSIONTIMER|
        DCD     &00000000                       ; Word r/w (referenced)

|MISSIONDATAARRAY|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     MemTargetDataArray                       ;~~ Word -/-
        DCD     &00024014                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     MemAircraftDataArray                       ;~~~ Word -/-
        DCD     &0002324C                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     MemTargetDataArray                       ;~~ Word -/-
        DCD     &00024014                       ;~~~ Word -/-
        DCD     &00024034                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     MemTargetDataArray                       ;~~ Word -/-
        DCD     &00024014                       ;~~~ Word -/-
        DCD     &00024034                       ;~~~ Word -/-
        DCD     &00024054                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     MemTargetDataArray                       ;~~ Word -/-
        DCD     &00024014                       ;~~~ Word -/-
        DCD     &00024034                       ;~~~ Word -/-
        DCD     &00024054                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     MemAircraftDataArray                       ;~~~ Word -/-
        DCD     &0002324C                       ;~~~ Word -/-
        DCD     &00023304                       ;~~~ Word -/-
        DCD     &000233BC                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     MemTargetDataArray                       ;~~ Word -/-
        DCD     &00024014                       ;~~~ Word -/-
        DCD     &00024034                       ;~~~ Word -/-
        DCD     &00024054                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     MemAircraftDataArray                       ;~~~ Word -/-
        DCD     &0002324C                       ;~~~ Word -/-
        DCD     &00023304                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     MemTargetDataArray                       ;~~ Word -/-
        DCD     &00024014                       ;~~~ Word -/-
        DCD     &00024034                       ;~~~ Word -/-
        DCD     &00024054                       ;~~~ Word -/-
        DCD     &00024074                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     MemAircraftDataArray                       ;~~~ Word -/-
        DCD     &0002324C                       ;~~~ Word -/-
        DCD     &00023304                       ;~~~ Word -/-
        DCD     &000233BC                       ;~~ Word -/-
        DCD     &00023474                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     MemTargetDataArray                       ;~~ Word -/-
        DCD     &00024014                       ;~~~ Word -/-
        DCD     &00024034                       ;~~~ Word -/-
        DCD     &00024054                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     MemTargetDataArray                       ;~~ Word -/-
        DCD     &00024014                       ;~~~ Word -/-
        DCD     &00024034                       ;~~~ Word -/-
        DCD     &00024054                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     MemAircraftDataArray                       ;~~~ Word -/-
        DCD     &0002324C                       ;~~~ Word -/-
        DCD     &00023304                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     MemTargetDataArray                       ;~~ Word -/-
        DCD     &00024014                       ;~~~ Word -/-
        DCD     &00024034                       ;~~~ Word -/-
        DCD     &00024054                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     MemAircraftDataArray                       ;~~~ Word -/-
        DCD     &0002324C                       ;~~~ Word -/-
        DCD     &00023304                       ;~~~ Word -/-
        DCD     &000233BC                       ;~~ Word -/-
        DCD     &00023474                       ;~~~ Word -/-
        DCD     &0002352C                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     MemTargetDataArray                       ;~~ Word -/-
        DCD     &00024014                       ;~~~ Word -/-
        DCD     &00024034                       ;~~~ Word -/-
        DCD     &00024054                       ;~~~ Word -/-
        DCD     &00024074                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     MemAircraftDataArray                       ;~~~ Word -/-
        DCD     &0002324C                       ;~~~ Word -/-
        DCD     &00023304                       ;~~~ Word -/-
        DCD     &000233BC                       ;~~ Word -/-
        DCD     &00023474                       ;~~~ Word -/-
        DCD     &0002352C                       ;~~~ Word -/-
        DCD     &000235E4                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     MemTargetDataArray                       ;~~ Word -/-
        DCD     &00024014                       ;~~~ Word -/-
        DCD     &00024034                       ;~~~ Word -/-
        DCD     &00024054                       ;~~~ Word -/-
        DCD     &00024074                       ;~~~ Word -/-
        DCD     &00024094                       ;~~~ Word -/-
        DCD     &000240B4                       ;~~ Word -/-
        DCD     &000240D4                       ;~~ Word -/-

        DCD     MemAircraftDataArray                       ;~~~ Word -/-
        DCD     &0002324C                       ;~~~ Word -/-
        DCD     &00023304                       ;~~~ Word -/-
        DCD     &000233BC                       ;~~ Word -/-
        DCD     &00023474                       ;~~~ Word -/-
        DCD     &0002352C                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     MemTargetDataArray                       ;~~ Word -/-
        DCD     &00024014                       ;~~~ Word -/-
        DCD     &00024034                       ;~~~ Word -/-
        DCD     &00024054                       ;~~~ Word -/-
        DCD     &00024074                       ;~~~ Word -/-
        DCD     &00024094                       ;~~~ Word -/-
        DCD     &000240B4                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     MemAircraftDataArray                       ;~~~ Word -/-
        DCD     &0002324C                       ;~~~ Word -/-
        DCD     &00023304                       ;~~~ Word -/-
        DCD     &000233BC                       ;~~ Word -/-
        DCD     &00023474                       ;~~~ Word -/-
        DCD     &0002352C                       ;~~~ Word -/-
        DCD     &000235E4                       ;~~~ Word -/-
        DCD     &0002369C                       ;~~~ Word -/-
        DCD     MemTargetDataArray                       ;~~ Word -/-
        DCD     &00024014                       ;~~~ Word -/-
        DCD     &00024034                       ;~~~ Word -/-
        DCD     &00024054                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     MemAircraftDataArray                       ;~~~ Word -/-
        DCD     &0002324C                       ;~~~ Word -/-
        DCD     &00023304                       ;~~~ Word -/-
        DCD     &000233BC                       ;~~ Word -/-
        DCD     &00023474                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     MemTargetDataArray                       ;~~ Word -/-
        DCD     &00024014                       ;~~~ Word -/-
        DCD     &00024034                       ;~~~ Word -/-
        DCD     &00024054                       ;~~~ Word -/-
        DCD     &00024074                       ;~~~ Word -/-
        DCD     &00024094                       ;~~~ Word -/-
        DCD     &000240B4                       ;~~ Word -/-
        DCD     &000240D4                       ;~~ Word -/-

        DCD     MemAircraftDataArray                       ;~~~ Word -/-
        DCD     &0002324C                       ;~~~ Word -/-
        DCD     &00023304                       ;~~~ Word -/-
        DCD     &000233BC                       ;~~ Word -/-
        DCD     &00023474                       ;~~~ Word -/-
        DCD     &0002352C                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     MemTargetDataArray                       ;~~ Word -/-
        DCD     &00024014                       ;~~~ Word -/-
        DCD     &00024034                       ;~~~ Word -/-
        DCD     &00024054                       ;~~~ Word -/-
        DCD     &00024074                       ;~~~ Word -/-
        DCD     &00024094                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     MemAircraftDataArray                       ;~~~ Word -/-
        DCD     &0002324C                       ;~~~ Word -/-
        DCD     &00023304                       ;~~~ Word -/-
        DCD     &000233BC                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     MemTargetDataArray                       ;~~ Word -/-
        DCD     &00024014                       ;~~~ Word -/-
        DCD     &00024034                       ;~~~ Word -/-
        DCD     &00024054                       ;~~~ Word -/-
        DCD     &00024074                       ;~~~ Word -/-
        DCD     &00024094                       ;~~~ Word -/-
        DCD     &000240B4                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     MemAircraftDataArray                       ;~~~ Word -/-
        DCD     &0002324C                       ;~~~ Word -/-
        DCD     &00023304                       ;~~~ Word -/-
        DCD     &000233BC                       ;~~ Word -/-
        DCD     &00023474                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     MemTargetDataArray                       ;~~ Word -/-
        DCD     &00024014                       ;~~~ Word -/-
        DCD     &00024034                       ;~~~ Word -/-
        DCD     &00024054                       ;~~~ Word -/-
        DCD     &00024074                       ;~~~ Word -/-
        DCD     &00024094                       ;~~~ Word -/-
        DCD     &000240B4                       ;~~ Word -/-
        DCD     &000240D4                       ;~~ Word -/-

        DCD     MemAircraftDataArray                       ;~~~ Word -/-
        DCD     &0002324C                       ;~~~ Word -/-
        DCD     &00023304                       ;~~~ Word -/-
        DCD     &000233BC                       ;~~ Word -/-
        DCD     &00023474                       ;~~~ Word -/-
        DCD     &0002352C                       ;~~~ Word -/-
        DCD     &000235E4                       ;~~~ Word -/-
        DCD     &0002369C                       ;~~~ Word -/-
        DCD     MemTargetDataArray                       ;~~ Word -/-
        DCD     &00024014                       ;~~~ Word -/-
        DCD     &00024034                       ;~~~ Word -/-
        DCD     &00024054                       ;~~~ Word -/-
        DCD     &00024074                       ;~~~ Word -/-
        DCD     &00024094                       ;~~~ Word -/-
        DCD     &000240B4                       ;~~ Word -/-
        DCD     &000240D4                       ;~~ Word -/-

        DCD     MemAircraftDataArray                       ;~~~ Word -/-
        DCD     &0002324C                       ;~~~ Word -/-
        DCD     &00023304                       ;~~~ Word -/-
        DCD     &000233BC                       ;~~ Word -/-
        DCD     &00023474                       ;~~~ Word -/-
        DCD     &0002352C                       ;~~~ Word -/-
        DCD     &000235E4                       ;~~~ Word -/-
        DCD     &0002369C                       ;~~~ Word -/-
        DCD     MemTargetDataArray                       ;~~ Word -/-
        DCD     &00024014                       ;~~~ Word -/-
        DCD     &00024034                       ;~~~ Word -/-
        DCD     &00024054                       ;~~~ Word -/-
        DCD     &00024074                       ;~~~ Word -/-
        DCD     &00024094                       ;~~~ Word -/-
        DCD     &000240B4                       ;~~ Word -/-
        DCD     &000240D4                       ;~~ Word -/-

        DCD     MemAircraftDataArray                       ;~~~ Word -/-
        DCD     &0002324C                       ;~~~ Word -/-
        DCD     &00023304                       ;~~~ Word -/-
        DCD     &000233BC                       ;~~ Word -/-
        DCD     &00023474                       ;~~~ Word -/-
        DCD     &0002352C                       ;~~~ Word -/-
        DCD     &000235E4                       ;~~~ Word -/-
        DCD     &0002369C                       ;~~~ Word -/-
        DCD     &00023754                       ;~~~ Word -/-
        DCD     &0002380C                       ;~~~ Word -/-
        DCD     &000238C4                       ;~~~ Word -/-
        DCD     &0002397C                       ;~~~ Word -/-
        DCD     &00023A34                       ;~~~ Word -/-
        DCD     &00023AEC                       ;~~~ Word -/-
        DCD     &00023BA4                       ;~~~ Word -/-
        DCD     &00023C5C                       ;~~~ Word -/-

        DCD     &00023D14                       ;~~~ Word -/-
        DCD     &00023DCC                       ;~~~ Word -/-
        DCD     &00023E84                       ;~~~ Word -/-
        DCD     &00023F3C                       ;~~~ Word -/-
        DCD     MemTargetDataArray                       ;~~ Word -/-
        DCD     &00024014                       ;~~~ Word -/-
        DCD     &00024034                       ;~~~ Word -/-
        DCD     &00024054                       ;~~~ Word -/-
        DCD     &00024074                       ;~~~ Word -/-
        DCD     &00024094                       ;~~~ Word -/-
        DCD     &000240B4                       ;~~ Word -/-
        DCD     &000240D4                       ;~~ Word -/-
        DCD     &000240F4                       ;~~ Word -/-
        DCD     &00024114                       ;~~~ Word -/-
        DCD     &00024134                       ;~~~ Word -/-
        DCD     &00024154                       ;~~~ Word -/-

        DCD     &00024174                       ;~~~ Word -/-
        DCD     &00024194                       ;~~~ Word -/-
        DCD     &000241B4                       ;~~ Word -/-
        DCD     &000241D4                       ;~~ Word -/-
        DCD     &000241F4                       ;~~ Word -/-
        DCD     &00024214                       ;~~~ Word -/-
        DCD     &00024234                       ;~~~ Word -/-
        DCD     &00024254                       ;~~~ Word -/-
|JSBUT0|
        DCD     &00000000                       ; Word r/w (referenced)
|JSBUT1|
        DCD     &00000000                       ; Word -/w (referenced)
|JSBUT2|
        DCD     &00000000                       ; Word -/w (referenced)
|JSBUT3|
        DCD     &00000000                       ; Word -/w (referenced)
|JSBUT4|
        DCD     &00000000                       ; Word -/w (referenced)

|GOTHA|
        ADD     R0,R0,#AircraftCoord                      ; =20, Function entry, (alters flags)
        LDMIA   R0,{R0-R2}
        STR     R14,|RETFROMGOTHA|                 ; -> Word: &00000000
        BL      |SERVICEFLAKGUN|
        LDR     R14,|RETFROMGOTHA|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|SERVICECAMERAPLANE|
        LDR     R1,[R0,#AircraftDamage]                   ; =56, Function entry, (alters flags)
        CMP     R1,#(FatalAircraftDamage-1)                      ; =10
        BGT     |CAMERAISDYING|

        MOV     PC,R14                          ; Function exit, Ends

|CAMERAISDYING|
        STR     R14,|RETURNFROMSERVICECAMERAPLANE|                 ; -> Word: &00000000

        CMP     R1,#DeadAircraftDamage                         ; =30
        LDRLT   R2,[R0,#AircraftCoordCopyY]                   ; =160
        LDRLT   R3,|PTARGETDATAARRAY3|                  ; -> Word: &0001462C
        LDRLT   R3,[R3,#0]
        ADDLT   R2,R2,R3
        MOVLT   R3,#0
        STRLT   R3,[R2,#TargetHitpoints]                   ; =28
        MOVLT   R1,#DeadAircraftDamage                         ; =30
        ADD     R1,R1,#1
        STR     R1,[R0,#AircraftDamage]                   ; =56

        LDR     R14,|PRACTICEADDR2|                 ; -> Word: &00011FC8
        LDR     R14,[R14,#0]
        CMP     R14,#1
        MOVEQ   R14,#PracticeReviveAircraftDamage       ; =&200
        MOVNE   R14,#ReviveAircraftDamage               ; =&1000000
        CMP     R1,R14
        BGT     |REINCARNATECAMERAPLANE|

        LDR     R14,|RETURNFROMSERVICECAMERAPLANE|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|REINCARNATECAMERAPLANE|
        ADD     R1,R0,#AircraftBackup                      ; ="D" (68)
        LDMIA   R1!,{R2-R12}
        STMIA   R0!,{R2-R12}
        LDMIA   R1!,{R2-R7}
        STMIA   R0!,{R2-R7}
        LDR     R14,|RETURNFROMSERVICECAMERAPLANE|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|RETURNFROMSERVICECAMERAPLANE|
        DCD     &00000000                       ; Word r/w (referenced)
|PTARGETDATAARRAY3|
        DCD     |TARGETDATAARRAY|
|PRACTICEADDR2|
        DCD     |ISPRACTICEMISSION|

|AIRCRAFTISCRASHING|
        LDR     R1,[R0,#AircraftDamage]                   ; =56
        ADD     R1,R1,#1
        STR     R1,[R0,#AircraftDamage]                   ; =56
        CMP     R1,#MaxAircraftDamage                     ; ="#" (35)
        BEQ     |TARGETAIRCRAFTDESTROYED|

        LDR     R14,|PRACTICEADDR2|                 ; -> Word: &00011FC8
        LDR     R14,[R14,#0]
        CMP     R14,#1
        MOVEQ   R14,#PracticeReviveAircraftDamage   ; =&200
        MOVNE   R14,#ReviveAircraftDamage      ; =&1000000
        CMP     R1,R14
        BGT     |REINCARNATE|

        B       |DONECAMERAPLANE|                     ; Ends

|REINCARNATE|
        ADD     R1,R0,#AircraftBackup                      ; ="D" (68)
        LDMIA   R1!,{R2-R12}
        STMIA   R0!,{R2-R12}
        LDMIA   R1!,{R2-R7}
        STMIA   R0!,{R2-R7}
        B       |DONECAMERAPLANE|                     ; Ends

|RETFROMGOTHA|
        DCD     &00000000                       ; Word r/w (referenced)
|PPLAYER1COORDS3|
        DCD     |PLAYER1COORDS|
|PPLAYER2COORDS3|
        DCD     |PLAYER2COORDS|

|CHECKAIRCRAFTCOLLISION|
        LDR     R0,|PPLAYER1COORDS3|                  ; -> Word: &00019AB8, Function entry, (alters flags)
        LDR     R5,|PPLAYER2COORDS3|                  ; -> Word: &00019CC4
        LDR     R2,[R0,#(AircraftDamage-AircraftCoord)]                   ; =36
        CMP     R2,#FatalAircraftDamage                         ; =11
        BGT     |NOAIRCRAFTCOLLISION|

        LDR     R2,[R5,#(AircraftDamage-AircraftCoord)]                   ; =36
        CMP     R2,#FatalAircraftDamage                         ; =11
        BGT     |NOAIRCRAFTCOLLISION|

        LDMIA   R0,{R2-R4}
        LDMIA   R5,{R6-R8}
        XABSDIFF R2,R2,R6
        XABSDIFF R3,R3,R7
        XABSDIFF R4,R4,R8
        CMP     R2,#&19,20                      ; =&19000
        BGT     |NOAIRCRAFTCOLLISION|
        CMP     R3,#&19,20                      ; =&19000
        BGT     |NOAIRCRAFTCOLLISION|
        CMP     R4,#&32,22                      ; =&C800
        BGT     |NOAIRCRAFTCOLLISION|
        B       |AIRCRAFTCOLLISION|                     ; Ends

|NOAIRCRAFTCOLLISION|
        LDR     R9,|PPLAYER2COORDS3|                  ; -> Word: &00019CC4
        LDMIA   R9,{R10-R12}

        LDR     R0,|P2AIRCRAFTPTRARRAYOFFSET|                  ; -> Word: &00012D94
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BEQ     |NOAIRCRAFTFORP2TOHIT|

        LDR     R1,|AIRCRAFTPTRARRAY2|                  ; -> Word: MemAircraftPointerArray
|CHECKP2COLLWITHAIRCRAFTLOOP|
        LDR     R2,[R1,#0]
        LDR     R7,[R2,#AircraftType]                   ; =140
        CMP     R7,#ATYPE_GOTHA_G_IV_BOMBER
        CMPNE   R7,#ATYPE_CARGO_AIRCRAFT
        MOVEQ   R7,#BigAircraftPlayerCollSizeXY ; =&7D000
        MOVNE   R7,#SmallAircraftPlayerCollSizeXY ; =&19000

        ADD     R2,R2,#AircraftCoord                      ; =20
        LDMIA   R2,{R3-R5}

        SUB     R3,R3,R10
        SUB     R4,R4,R11
        SUB     R5,R5,R12

        ; Make distance absolute
        XABS    R3
        XABS    R4
        XABS    R5

        CMP     R3,R7
        BGT     |CHECKP2COLLWITHNEXTAIRCRAFT|
        CMP     R4,R7
        BGT     |CHECKP2COLLWITHNEXTAIRCRAFT|
        CMP     R5,#AircraftPlayerCollSizeZ       ; =&19000
        BGT     |CHECKP2COLLWITHNEXTAIRCRAFT|

        B       |MIDAIRCRASH|                     ; Ends

|CHECKP2COLLWITHNEXTAIRCRAFT|
        SUB     R0,R0,#4
        ADD     R1,R1,#BytesPerAddress
        CMP     R0,#0
        BGT     |CHECKP2COLLWITHAIRCRAFTLOOP|

|NOAIRCRAFTFORP2TOHIT|
        LDR     R9,|PPLAYER1COORDS3|                  ; -> Word: &00019AB8
        LDMIA   R9,{R10-R12}

        LDR     R0,|P2AIRCRAFTPTRARRAYOFFSET|                  ; -> Word: &00012D94
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BEQ     |NOAIRCRAFTFORP1TOHIT|

        LDR     R1,|AIRCRAFTPTRARRAY2|                  ; -> Word: MemAircraftPointerArray
|CHECKP1COLLWITHAIRCRAFTLOOP|
        LDR     R2,[R1,#0]
        LDR     R7,[R2,#AircraftType]                   ; =140
        CMP     R7,#ATYPE_GOTHA_G_IV_BOMBER
        CMPNE   R7,#ATYPE_CARGO_AIRCRAFT
        MOVEQ   R7,#BigAircraftPlayerCollSizeXY  ; =&7D000
        MOVNE   R7,#SmallAircraftPlayerCollSizeXY       ; =&19000
        ADD     R2,R2,#AircraftCoord                      ; =20
        LDMIA   R2,{R3-R5}
        SUB     R3,R3,R10
        SUB     R4,R4,R11
        SUB     R5,R5,R12

        ; Make distance absolute
        XABS    R3
        XABS    R4
        XABS    R5

        CMP     R3,R7
        BGT     |CHECKP1COLLWITHNEXTAIRCRAFT|
        CMP     R4,R7
        BGT     |CHECKP1COLLWITHNEXTAIRCRAFT|
        CMP     R5,#AircraftPlayerCollSizeZ       ; =&19000
        BGT     |CHECKP1COLLWITHNEXTAIRCRAFT|

        B       |MIDAIRCRASH|                     ; Ends

|CHECKP1COLLWITHNEXTAIRCRAFT|
        SUB     R0,R0,#4
        ADD     R1,R1,#BytesPerAddress
        CMP     R0,#0
        BGT     |CHECKP1COLLWITHAIRCRAFTLOOP|

|NOAIRCRAFTFORP1TOHIT|
        LDR     R0,|PTARGETARRAYWRITEOFFSET|                  ; -> Word: &00013754
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BEQ     |L00007404|
        LDR     R1,|TARGETPTRARRAY3|                  ; -> Word: MemTargetPointerArray
|TARGETLOOP|
        LDR     R9,[R1,#0]
        LDMIA   R9,{R3-R8}
        MVN     R3,R3,LSL #10
        MVN     R4,R4,LSL #10
        MVN     R5,R5,LSL #10
        SUB     R3,R3,R10
        SUB     R4,R4,R11
        SUB     R5,R5,R12

        ; Make distance absolute
        XABS    R3
        XABS    R4
        XABS    R5

        ADD     R6,R6,#&32,22                   ; =&C800
        ADD     R7,R7,#&32,22                   ; =&C800
        ADD     R8,R8,#&32,24                   ; =&3200
        CMP     R3,R6
        BGT     |NEXTTARGET|

        CMP     R4,R7
        BGT     |NEXTTARGET|

        CMP     R5,R8
        BGT     |CHECKFORBALLOON|

        B       |COLLISION|                     ; Ends

|CHECKFORBALLOON|
        LDR     R9,[R9,#TargetType]                   ; =24
        CMP     R9,#TTYPE_BARRAGE_BALLOON
        BNE     |NEXTTARGET|

        CMP     R12,#&FA,18                     ; =&3E8000
        BGT     |NEXTTARGET|

        MOV     R7,#&32,22                      ; =&C800
        CMP     R4,R7
        BGT     |NEXTTARGET|

        B       |COLLISION|                     ; Ends

|NEXTTARGET|
        SUB     R0,R0,#4
        ADD     R1,R1,#BytesPerAddress
        CMP     R0,#0
        BGT     |TARGETLOOP|
|L00007404|
        LDR     R0,|L00007570|                  ; -> Word: &00000000
        LDR     R1,|COLLISIONINFO|                  ; -> Word: MemCollisionBoxes
|CHECKCOLLISIONLOOP|
        LDMIA   R1!,{R2-R7}

        XABSDIFF R2,R2,R10
        XABSDIFF R3,R3,R11
        XABSDIFF R4,R4,R12

        CMP     R2,R5
        BGT     |NOCOLLISION2|

        CMP     R3,R6
        BGT     |NOCOLLISION2|

        CMP     R4,R7
        BGT     |NOCOLLISION2|

        B       |COLLISION|                     ; Ends

|NOCOLLISION2|
        SUBS    R0,R0,#1
        BPL     |CHECKCOLLISIONLOOP|

        LDR     R0,|PSPLITSCREEN8|                  ; -> Word: &00016B28
        LDR     R0,[R0,#0]
        CMP     R0,#0
        MOVEQ   PC,R14                          ; Function exit if EQ

        LDR     R0,|L00007570|                  ; -> Word: &00000000
        LDR     R1,|COLLISIONINFO|                  ; -> Word: MemCollisionBoxes
        LDR     R2,|PPLAYER2INFO14|                  ; -> Word: &00019CB0
        ADD     R2,R2,#AircraftCoord                      ; =20
        LDMIA   R2,{R10-R12}
|CHECKCOLLISIONP2LOOP|
        LDMIA   R1!,{R2-R7}

        XABSDIFF R2,R2,R10
        XABSDIFF R3,R3,R11
        XABSDIFF R4,R4,R12

        CMP     R2,R5
        BGT     |NOCOLLISIONP2|

        CMP     R3,R6
        BGT     |NOCOLLISIONP2|

        CMP     R4,R7
        BGT     |NOCOLLISIONP2|

        B       |COLLISIONP2|                     ; Ends
|NOCOLLISIONP2|
        SUBS    R0,R0,#1
        BPL     |CHECKCOLLISIONP2LOOP|

        LDR     R0,|PTARGETARRAYWRITEOFFSET|                  ; -> Word: &00013754
        LDR     R0,[R0,#0]
        CMP     R0,#0
        MOVEQ   PC,R14                          ; Function exit if EQ

        LDR     R1,|TARGETPTRARRAY3|                  ; -> Word: MemTargetPointerArray
|LCHECKCOLLISIONP2LOOPB|
        LDR     R9,[R1,#0]
        LDMIA   R9,{R3-R8}
        MVN     R3,R3,LSL #10
        MVN     R4,R4,LSL #10
        MVN     R5,R5,LSL #10
        SUB     R3,R3,R10
        SUB     R4,R4,R11
        SUB     R5,R5,R12

        ; Make distance absolute
        XABS    R3
        XABS    R4
        XABS    R5

        ADD     R6,R6,#&32,22                   ; =&C800
        ADD     R7,R7,#&32,22                   ; =&C800
        ADD     R8,R8,#&32,24                   ; =&3200
        CMP     R3,R6
        BGT     |NOCOLLISIONP2B|
        CMP     R4,R7
        BGT     |NOCOLLISIONP2B|
        CMP     R5,R8
        BGT     |L00007524|
        B       |COLLISIONP2|                     ; Ends
|L00007524|
        LDR     R9,[R9,#TargetType]                   ; =24
        CMP     R9,#TTYPE_BARRAGE_BALLOON
        BNE     |NOCOLLISIONP2B|

        CMP     R12,#&FA,18                     ; =&3E8000
        BGT     |NOCOLLISIONP2B|

        MOV     R7,#&32,22                      ; =&C800
        CMP     R4,R7
        BGT     |NOCOLLISIONP2B|

        B       |COLLISIONP2|                     ; Ends
|NOCOLLISIONP2B|
        SUB     R0,R0,#4
        ADD     R1,R1,#BytesPerAddress
        CMP     R0,#0
        BGT     |LCHECKCOLLISIONP2LOOPB|
        MOV     PC,R14                          ; Function exit, Ends

|AIRCRAFTPTRARRAY2|
        DCD     MemAircraftPointerArray                       ; Word r/- (referenced)
|P2AIRCRAFTPTRARRAYOFFSET|
        DCD     |AIRCRAFTPTRARRAYOFFSET|
|TARGETPTRARRAY3|
        DCD     MemTargetPointerArray                       ; Word r/- (referenced)
|PTARGETARRAYWRITEOFFSET|
        DCD     |TARGETARRAYWRITEOFFSET|
|PPLAYERINFO14|
        DCD     |PLAYER1INFO|
|L00007570|
        DCD     &00000000                       ; Word r/- (referenced)
|COLLISIONINFO|
        DCD     MemCollisionBoxes                       ; Word r/- (referenced)
|P3OUTPUT|
        DCD     |OUTPUT|
|PSPLITSCREEN8|
        DCD     |SPLITSCREEN|
|PPLAYER2INFO14|
        DCD     |PLAYER2INFO|

|MIDAIRCRASH|
        LDR     R2,[R1,#0]
        MOV     R11,#FatalAircraftDamage                  ; =11

        LDR     R10,[R2,#AircraftDamage]                  ; =56
        CMP     R10,#FatalAircraftDamage                  ; =11
        STRLT   R11,[R2,#AircraftDamage]                  ; =56

        LDR     R10,[R9,#(AircraftDamage-AircraftCoord)]        ; =36
        CMP     R10,#FatalAircraftDamage                        ; =11
        STRLT   R11,[R9,#(AircraftDamage-AircraftCoord)]        ; =36

        MOV     R1,R14
        LDMIA   R9,{R2-R4}
        MOV     R5,#0
        BL      |ADDEXPLOSION|
        MOV     PC,R1                           ; Ends, Dynamic branch

|AIRCRAFTCOLLISION|
        MOV     R11,#FatalAircraftDamage                        ; =11
        LDR     R10,[R0,#(AircraftDamage-AircraftCoord)]                  ; =36
        CMP     R10,#FatalAircraftDamage                        ; =11
        STRLT   R11,[R0,#(AircraftDamage-AircraftCoord)]                  ; =36
        LDR     R10,[R5,#(AircraftDamage-AircraftCoord)]                  ; =36
        CMP     R10,#FatalAircraftDamage                        ; =11
        STRLT   R11,[R5,#(AircraftDamage-AircraftCoord)]                  ; =36
        MOV     R1,R14
        LDMIA   R0,{R2-R4}
        MOV     R5,#0
        BL      |ADDEXPLOSION|
        MOV     PC,R1                           ; Ends, Dynamic branch

|COLLISION|
        MOV     R11,#CrashDamage                ; =13
        LDR     R0,|PPLAYERINFO14|                  ; -> Word: &00019AA4
        LDR     R10,[R0,#AircraftDamage]                  ; =56
        CMP     R10,#FatalAircraftDamage                        ; =11
        STRLT   R11,[R0,#AircraftDamage]                  ; =56

        LDR     R11,[R0,#AircraftSerialBitMask]                  ; =152
        ADD     R11,R11,#AircraftSerialBitCrash                    ; =" " (32)
        STR     R11,[R0,#AircraftSerialBitMask]                  ; =152

        LDR     R11,|P3OUTPUT|                 ; -> Word: &00017A54
        MOV     R10,#OutputCollision
        STR     R10,[R11,#0]

        MOV     PC,R14                          ; Function exit, Ends

|COLLISIONP2|
        MOV     R11,#CrashDamage                ; =13
        LDR     R0,|PPLAYER2INFO14|                  ; -> Word: &00019CB0
        LDR     R10,[R0,#AircraftDamage]                  ; =56
        CMP     R10,#FatalAircraftDamage                        ; =11
        STRLT   R11,[R0,#AircraftDamage]                  ; =56

        LDR     R11,[R0,#AircraftSerialBitMask]                  ; =152
        ADD     R11,R11,#AircraftSerialBitCrash                    ; =" " (32)
        STR     R11,[R0,#AircraftSerialBitMask]                  ; =152

        LDR     R11,|P3OUTPUT|                 ; -> Word: &00017A54
        MOV     R10,#OutputCollision
        STR     R10,[R11,#0]

        MOV     PC,R14                          ; Function exit, Ends

|DUPFRAMEBUFFERADDR|
        LDR     R0,|PFRAMEBUFFER|                  ; -> Word: &0001204C, Function entry, (alters flags)
        LDR     R1,[R0,#0]

        LDR     R0,|PFRAMEBUFFER2|                  ; -> Word: &00013700
        STR     R1,[R0,#0]

        LDR     R0,|PFRAMEBUFFERCOPY2|                  ; -> Word: &00014C38
        STR     R1,[R0,#0]

        LDR     R0,|PMAXCOORDY4|                  ; -> Word: &00012050
        LDR     R1,[R0,#0]

        LDR     R0,|PMAXCOORDY7|                  ; -> Word: &000136FC
        STR     R1,[R0,#0]

        LDR     R0,|PMAXCOORDY8|                  ; -> Word: &00014C34
        STR     R1,[R0,#0]

        MOV     PC,R14                          ; Function exit, Ends

|PFRAMEBUFFER|
        DCD     |FRAMEBUFFER|
|PFRAMEBUFFER2|
        DCD     |FRAMEBUFFER2|
|PFRAMEBUFFERCOPY2|
        DCD     |FRAMEBUFFERCOPY|
|PMAXCOORDY4|
        DCD     |MAXCOORDY4|
|PMAXCOORDY7|
        DCD     |MAXCOORDY7|
|PMAXCOORDY8|
        DCD     |MAXCOORDY8|

|AMENDAIRCRAFTANGLES|
        ; R1 = AircraftPitch
        ; R3 = AircraftRoll
        ; R10 = AircraftViewQuarter
        ; R11 = AircraftViewAngle
        ; R12 = AircraftViewIn
        MOV     R0,R1,ASR #AngleShift                   ; Function entry, (alters flags)
        BIC     R0,R0,#AngleStepMask
        STR     R0,|AIRCRAFTPITCH|                  ; -> Word: &00000000

        LDR     R0,|THREEQUARTERTURN2|                  ; -> Word: &00438000
        CMP     R1,R0
        MOVGT   R0,#ATYPE_PLAYER
        MOVLT   R0,#ATYPE_CAMERA

        CMP     R1,#QuarterTurn:SHL:AngleShift                      ; =&168000
        MOVLT   R0,#ATYPE_PLAYER

        STR     R0,|AIRCRAFTTYPE|                  ; -> Word: &00000000

        CMP     R12,#ViewOutside
        MOVEQ   PC,R14                          ; Function exit if EQ

        CMP     R10,#QuarterFront
        MOVEQ   PC,R14                          ; Function exit if EQ

        CMP     R10,#QuarterBack
        MOVEQ   PC,R14                          ; Function exit if EQ

        ; We have a side view from inside
        CMP     R0,#ATYPE_CAMERA
        RSBEQ   R3,R3,#0 ; reverse AircraftRoll

        CMP     R3,#0
        ADDLT   R3,R3,#FullRotation:SHL:AngleShift                   ; =&5A0000

        CMP     R3,#QuarterTurn:SHL:AngleShift                      ; =&168000
        MOVLT   PC,R14                          ; Function exit if LT

        LDR     R0,|THREEQUARTERTURN5|                  ; -> Word: &00438000
        CMP     R3,R0 ; AircraftRoll > 270 deg?
        MOVGT   PC,R14                          ; Function exit if GT

        RSB     R1,R1,#0 ; reverse AircraftPitch
        CMP     R1,#0
        ADDLT   R1,R1,#FullRotation:SHL:AngleShift                   ; =&5A0000

        MOV     PC,R14                          ; Function exit, Ends

|SETAIRCRAFTTYPE|
        LDR     R10,|PPLAYER1INFO15|                 ; -> Word: &00019AA4, Function entry, (alters flags)
        LDR     R1,[R10,#AircraftPitch]

        LDR     R0,|THREEQUARTERTURN2|                  ; -> Word: &00438000
        CMP     R1,R0
        MOVGT   R0,#ATYPE_PLAYER
        MOVLT   R0,#ATYPE_CAMERA

        CMP     R1,#QuarterTurn:SHL:AngleShift                      ; =&168000
        MOVLT   R0,#ATYPE_PLAYER
        STR     R0,[R10,#AircraftType]                  ; =140

        ; Same for player 2
        LDR     R10,|PPLAYER2INFO15|                 ; -> Word: &00019CB0
        LDR     R1,[R10,#AircraftPitch]

        LDR     R0,|THREEQUARTERTURN2|                  ; -> Word: &00438000
        CMP     R1,R0
        MOVGT   R0,#ATYPE_PLAYER
        MOVLT   R0,#ATYPE_CAMERA

        CMP     R1,#QuarterTurn:SHL:AngleShift                      ; =&168000
        MOVLT   R0,#ATYPE_PLAYER
        STR     R0,[R10,#AircraftType]                  ; =140

        MOV     PC,R14                          ; Function exit, Ends

|PPLAYER1INFO15|
        DCD     |PLAYER1INFO|
|PPLAYER2INFO15|
        DCD     |PLAYER2INFO|
|THREEQUARTERTURN5|
        DCD     (3*QuarterTurn):SHL:AngleShift                       ; Word r/- (referenced)
|AIRCRAFTPITCH|
        DCD     &00000000                       ; Word -/w (referenced)
|AIRCRAFTTYPE|
        DCD     ATYPE_PLAYER                  ; Word -/w (referenced)
|THREEQUARTERTURN2|
        DCD     (QuarterTurn*3):SHL:AngleShift  ; Word r/- (referenced)
|PJSENABLE|
        DCD     |JSENABLE|

|READJSBUT|
        LDR     R0,|PJSENABLE|                  ; -> Word: &00015164, Function entry, (alters flags)
        LDR     R0,[R0,#0]
        CMP     R0,#0
        MOVEQ   PC,R14                          ; Function exit if EQ

        SWI     XJoy_Read0
        MOV     R1,R0

        SWI     XJoy_Read1
        ORR     R0,R0,R1

        BIC     R1,R0,#&0F                      ; =15
        STR     R1,|JSBUT0|                  ; -> Word: &00000000

        BIC     R1,R0,#&17                      ; =23
        STR     R1,|JSBUT1|                  ; -> Word: &00000000

        BIC     R1,R0,#&1B                      ; =27
        STR     R1,|JSBUT2|                  ; -> Word: &00000000

        BIC     R1,R0,#&1D                      ; =29
        STR     R1,|JSBUT3|                  ; -> Word: &00000000

        BIC     R1,R0,#&1E                      ; =30
        STR     R1,|JSBUT4|                  ; -> Word: &00000000

        MOV     PC,R14                          ; Function exit, Ends

|DRAWCROSSHAIR|
        LDR     R0,|P2PPLAYERINFO2|                  ; -> Word: &00012048, Function entry, (alters flags)
        LDR     R0,[R0,#0]
        LDR     R0,[R0,#PlayerCrossHair]                   ; =284
        CMP     R0,#0
        MOVEQ   PC,R14                          ; Function exit if EQ

        STR     R14,|RETFROMDRAWCROSSHAIR|  ; -> Word: &00000000

        MVN     R0,#(CrossHairWidth-1)    ; ="E" (69)
        MOV     R1,#0
        MOV     R2,#CrossHairWidth      ; ="F" (70)
        MOV     R3,#0
        LDR     R4,|CROSSHAIRCOLOUR|                  ; -> Word: &00000000
        BL      |DRAW2DLINE|

        MOV     R0,#0
        MOV     R1,#0
        MOV     R2,#0
        MVN     R3,#(CrossHairHeight-1)   ; =30
        LDR     R4,|CROSSHAIRCOLOUR|                  ; -> Word: &00000000
        BL      |DRAW2DLINE|

        LDR     R14,|RETFROMDRAWCROSSHAIR| ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|L0000780C|
        DCD     &00000001                       ;~~~ Word -/-
|RETFROMDRAWCROSSHAIR|
        DCD     &00000000                       ; Word r/w (referenced)
|CROSSHAIRCOLOUR|
        DCD     &00000000                       ; Word r/- (referenced)
|P2PPLAYERINFO2|
        DCD     |PPLAYERINFO2|
|TMP|
        % 140

|DRAWBORDERS|
        LDR     R0,|PSPLITSCREEN9|                  ; -> Word array: &00016B28, Function entry, (alters flags)
        LDR     R0,[R0,#0]
        CMP     R0,#0
        MOVNE   PC,R14                          ; Function exit if NE

        STR     R14,|RETFROMDRAWBORDERS|        ; -> Word: &00000000

        LDR     R0,|PFRAMEBUFFER7|                  ; -> Word array: &0001204C
        LDR     R1,[R0,#0]
        SUB     R1,R1,#1
        STR     R1,[R0,#0]

        ; Draw left border
        MVN     R0,#((WIDTH/2)-2):SHL:CoordToScreenLog2 ; =&278
        MOV     R1,#((HEIGHT/2)+2):SHL:CoordToScreenLog2 ; =&208
        MVN     R2,#((WIDTH/2)-2):SHL:CoordToScreenLog2 ; =&278
        MVN     R3,#((HEIGHT/2)+2):SHL:CoordToScreenLog2 ; =&208
        MOV     R4,#Black
        BL      |DRAW2DLINE|

        LDR     R0,|PFRAMEBUFFER7|                  ; -> Word array: &0001204C
        LDR     R1,[R0,#0]
        ADD     R1,R1,#1
        STR     R1,[R0,#0]

        ; Draw right border
        MOV     R0,#((WIDTH/2)-1):SHL:CoordToScreenLog2 ; =&27C
        MOV     R1,#((HEIGHT/2)+2):SHL:CoordToScreenLog2 ; =&208
        MOV     R2,#((WIDTH/2)-1):SHL:CoordToScreenLog2 ; =&27C
        MVN     R3,#((HEIGHT/2)+2):SHL:CoordToScreenLog2  ; =&208
        MOV     R4,#Black
        BL      |DRAW2DLINE|

        LDR     R0,|L00007990|                  ; -> Word: &00019AA4
        LDR     R0,[R0,#PlayerAircraftToView]                   ; =264
        CMP     R0,#CamThisPlayer                         ; =20
        BNE     |DRAWBORDERS2| ; not the player's aircraft

        LDR     R0,|L00007990|                  ; -> Word: &00019AA4
        LDR     R1,[R0,#AircraftViewIn]                   ; =44
        CMP     R1,#ViewInside
        BNE     |DRAWBORDERS2| ; not an inside view

        LDR     R1,[R0,#AircraftViewQuarter]                   ; =36
        CMP     R1,#QuarterFront
        BEQ     |SKIPTOPNBOTTOMBORDER| ; inside front view of the player's aircraft

|DRAWBORDERS2|
        LDR     R0,|PFRAMEBUFFER12|                  ; -> Word: &0001BAB4
        LDR     R0,[R0,#0]

        ADR     R1,|BLACKSRC|                  ; -> Word array: &00000000
        LDMIA   R1,{R2-R11}

        MOV     R1,#((RowStride*TopBorderHeight)/PixelCopyChunk)-1  ; =15
        LDR     R12,|BOTTOMBORDEROFFSET|        ; -> Word: &00013C40
        ADD     R12,R12,R0
|DRAWBORDERSLOOP|
        STMIA   R0!,{R2-R11} ; 40 pixels
        STMIA   R12!,{R2-R11}
        SUBS    R1,R1,#1
        BPL     |DRAWBORDERSLOOP|

        ; Draw extra row at the bottom
count SETA 0
        WHILE count < (WIDTH/PixelCopyChunk)
        STMIA   R12!,{R2-R11}
count SETA count + 1
        WEND

|SKIPTOPNBOTTOMBORDER|
        LDR     R14,|RETFROMDRAWBORDERS|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|RETFROMDRAWBORDERS|
        DCD     &00000000                       ; Word r/w (referenced)
|L00007990|
        DCD     |PLAYER1INFO|
|PFRAMEBUFFER12|
        DCD     |FRAMEBUFFER12|
|BOTTOMBORDEROFFSET|
        DCD     (HEIGHT-3) * RowStride
        DCD     |PPLAYERINFO2|
|BLACKSRC|
        MAKEFILL Black

|PFRAMEBUFFER7|
        DCD     |FRAMEBUFFER|
|PSPLITSCREEN9|
        DCD     |SPLITSCREEN|
|ELECTRICBLUESRC|
        MAKEFILL MediumElectricBlue

|AIRCRAFTTOCAMERAVEC|
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
|DAMAGECOLOURS|
        DCB     Black,Black,Black,Black
        DCB     BrightRed,BrightRed,BrightRed,Black
        DCB     Yellow,Yellow,Yellow,Black
        DCB     Yellow,Yellow,Yellow,Black
        DCB     Green,Green,Green,Black
        DCB     Green,Green,Green,Black
        DCB     Green,Green,Green,Black

|DRAWDAMAGE|
        ; r0 = frame buffer address at which to draw the armour
        ; r1 = damage
        ADR     R10,|DAMAGECOLOURS|                 ; -> Word array: &00000000, Function entry, (alters flags)
        MOV     R6,#(NumDamageBars-1)
|DRAWDAMAGELOOP|
        MOV     R9,#Black ; top margin
        STR     R9,[R0,#0]

        LDR     R9,[R10,#0] ; coloured bar
        STR     R9,[R0,#RowStride]                   ; =5<<6
        STR     R9,[R0,#RowStride*2]                   ; =5<<7
        STR     R9,[R0,#RowStride*3]                   ; =&F<<6
        STR     R9,[R0,#RowStride*4]                   ; =5<<8

        MOV     R9,#Black ; bottom margin
        STR     R9,[R0,#RowStride*5]                   ; =&19<<6

        ADD     R10,R10,#DamageBarWidth ; next damage colour
        ADD     R0,R0,#DamageBarWidth ; next frame buffer address
        CMP     R1,#(FatalAircraftDamage-1)                      ; =10
        ADRGT   R10,|DAMAGECOLOURS| ; remaining bars are black
        ADD     R1,R1,#4

        SUBS    R6,R6,#1
        BPL     |DRAWDAMAGELOOP| ; draw next bar

        MOV     PC,R14                          ; Function exit, Ends

|ZEROSOMETHINGIFNOTPRACTICE|
        LDR     R0,|PRACTICEADDR3|                  ; -> Word: &00011FC8, Function entry, (alters flags)
        LDR     R0,[R0,#0]
        CMP     R0,#0
        MOVNE   R1,#0
        LDRNE   R2,|L00007AA8|                  ; -> Word: &00013DE0
        STRNE   R1,[R2,#0]
        MOV     PC,R14                          ; Function exit, Ends

|L00007AA8|
        DCD     |FLAKARRAYOFFSET|
|PRACTICEADDR3|
        DCD     |ISPRACTICEMISSION|
|PDEMOSTATUS|
        DCD     |DEMOSTATUS|
|PPPLAYERINFO2|
        DCD     |PPLAYERINFO2|
|AIRCRAFTDATAARRAY4|
        DCD     MemAircraftDataArray                       ; Word r/- (referenced)
|PTARGETDATAARRAY6|
        DCD     MemTargetDataArray                       ; Word r/- (referenced)
        DCD     |PLAYER1CAMERAPLANE|
        DCD     |PLAYER1GHOST|
|L00007AC8.String|
        DCB     "CHOCKS AWAY EXTRA MISSIONS DEMO",0 ; String r/- (referenced)

|DISPLAYDEMO|
        LDR     R0,|PDEMOSTATUS|                  ; -> Word: &00015DC4, Function entry, (alters flags)
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BEQ     |NODEMOSTRING|

        MOV     R0,#JoinCursors
        SWI     OS_WriteC

        MOV     R0,#SetCursorPos                         ; =31
        SWI     OS_WriteC

        MOV     R0,#SplitCursors
        SWI     OS_WriteC

        MOV     R0,#SplitCursors
        SWI     OS_WriteC

        ADR     R0,|L00007AC8.String|           ; -> String: "CHOCKS AWAY EXTRA MISSIONS DEMO",0
        SWI     OS_Write0

|NODEMOSTRING|
        LDR     R0,|PPPLAYERINFO2|                  ; -> Word: &00012048
        LDR     R0,[R0,#0]
        LDR     R0,[R0,#PlayerAircraftToView]                   ; =264
        CMP     R0,#CamThisPlayer                         ; =20
        CMPNE   R0,#CamOtherPlayer                         ; =21
        CMPNE   R0,#&7D                         ; ="}" (125)
        CMPNE   R0,#&7E                         ; ="~" (126)
        MOVEQ   PC,R14                          ; Function exit if EQ

        CMP     R0,#CamThisPlayer                         ; =20
        BGT     |L00007B68|

        MOV     R11,R0
        MOV     R1,#BytesPerAircraft                         ; ="" (184)
        MUL     R2,R1,R0
        LDR     R1,|AIRCRAFTDATAARRAY4|                  ; -> Word: MemAircraftDataArray
        ADD     R1,R1,R2
        LDR     R0,[R1,#AircraftType]                   ; =140
        LDR     R12,[R1,#AircraftViewIn]                  ; =44
        B       |DISPLAYVIEWMSG|                     ; Ends

|L00007B68|
        SUB     R0,R0,#CamTarget                      ; ="d" (100)
        MOV     R11,R0
        CMP     R0,#&17                         ; =23

        LDR     R12,|PPPLAYERINFO2|                 ; -> Word: &00012048
        LDR     R12,[R12,#0]
        LDRLT   R12,[R12,#PlayerCameraPlane]                 ; =280
        LDRGE   R12,[R12,#PlayerGhostPlane]                 ; =268
        LDR     R12,[R12,#AircraftViewIn]                 ; =44

        CMP     R0,#&14                         ; =20
        ADDGE   R0,R0,#&0E                      ; =14
        SUBGE   R11,R11,#&14                    ; =20
        BGE     |DISPLAYVIEWMSG|

        LDR     R1,|PTARGETDATAARRAY6|                  ; -> Word: MemTargetDataArray
        ADD     R1,R1,R0,LSL #BytesPerTargetLog2
        LDR     R0,[R1,#TargetType]                   ; =24
        ADD     R0,R0,#TargetTypeToMessage          ; =11

|DISPLAYVIEWMSG|
        ; R0 = message string index
        MOV     R1,#BytesPerMessageString        ; =31
        MUL     R2,R1,R0
        LDR     R1,|PCAMERAVIEWSTRINGS|                  ; -> Word: &000192A8
        ADD     R10,R1,R2

        LDR     R9,|PPPLAYERINFO2|                  ; -> Word: &00012048
        LDR     R9,[R9,#0]

        MOV     R0,#JoinCursors
        SWI     OS_WriteC

        MOV     R0,#SetCursorPos                         ; =31
        SWI     OS_WriteC

        LDR     R0,[R9,#&148]                   ; =328
        SWI     OS_WriteC

        LDR     R0,[R9,#&14C]                   ; =332
        SWI     OS_WriteC

        ADD     R1,R10,#&17                     ; =23
        CMP     R12,#ViewInside
        MOVEQ   R2,#"I"                         ; = (73)
        MOVEQ   R3,#"N"                         ; = (78)
        MOVEQ   R4,#" "                         ; = (32)
        MOV     R5,#" "                         ; = (32)
        MOVNE   R2,#"O"                         ; = (79)
        MOVNE   R3,#"U"                         ; = (85)
        MOVNE   R4,#"T"                         ; = (84)

        STRB    R2,[R1,#0]
        STRB    R3,[R1,#1]
        STRB    R4,[R1,#2]
        STRB    R5,[R1,#3]

        CMP     R11,#&0A                        ; =10
        SUBGE   R11,R11,#&0A                    ; =10
        MOVGE   R2,#"1"                         ; = (49)
        MOVLT   R2,#" "                         ; = (32)
        STRB    R2,[R1,#4]

        ADD     R2,R11,#"0"                     ; = (48)
        STRB    R2,[R1,#5]

        MOV     R0,R10
        SWI     OS_Write0

        MOV     PC,R14                          ; Function exit, Ends

|DISPLAYMSG|
        LDR     R0,|PPPLAYERINFO2|                  ; -> Word: &00012048, Function entry, (alters flags)
        LDR     R0,[R0,#0]

        ; Check for message timeout
        LDR     R1,[R0,#AircraftMsgRemain]                   ; =176
        CMP     R1,#0
        MOVEQ   PC,R14                          ; Function exit if EQ

        SUB     R1,R1,#1
        STR     R1,[R0,#AircraftMsgRemain]                   ; =176

        LDR     R2,[R0,#AircraftHideMsg]                   ; =172
        CMP     R2,#0
        MOVEQ   PC,R14                          ; Function exit if EQ

        ; Messages are allowed
        LDR     R2,[R0,#AircraftMsgNum]                   ; =180
        CMP     R2,#MsgRepairedRefuelled             ; ="#" (35)
        BNE     |NOTREPAIREDANDREFUELLED|

        LDR     R3,|PPPLAYERINFO|                  ; -> Word: &00012048
        LDR     R3,[R3,#0]
        LDR     R3,[R3,#PlayerAircraftToView]                   ; =264
        CMP     R3,#CamThisPlayer                         ; =20
        MOVNE   PC,R14                          ; Function exit if NE

|NOTREPAIREDANDREFUELLED|
        MOV     R0,#JoinCursors
        SWI     OS_WriteC

        LDR     R9,|PPPLAYERINFO2|                  ; -> Word: &00012048
        LDR     R9,[R9,#0]
        MOV     R0,#SetCursorPos                         ; =31
        SWI     OS_WriteC

        LDR     R0,[R9,#PlayerMessageCoordX]                   ; =5<<6
        SWI     OS_WriteC

        LDR     R0,[R9,#PlayerMessageCoordY]                   ; =324
        SWI     OS_WriteC

        MOV     R1,#BytesPerMessageString              ; =31
        MUL     R0,R1,R2
        LDR     R1,|PMESSAGESTRINGS|                  ; -> Word: &00018E4C
        ADD     R0,R0,R1
        SWI     OS_Write0

        MOV     PC,R14                          ; Function exit, Ends

|L00007CC4|
        DCD     &00000000                       ;~ Word -/-
|PMESSAGESTRINGS|
        DCD     |MESSAGESTRINGS|
|PCAMERAVIEWSTRINGS|
        DCD     |CAMERAVIEWSTRINGS|
        DCD     &00000000                       ;~ Word -/-
|PPPLAYERINFO|
        DCD     |PPLAYERINFO2|
|UNKNOWN|
        DCD     &00000000                       ;~ Word -/-
|MESSAGESTRINGS|
        DCB     "TIGER MOTH       (NOT A  IDEA)",0 ;~~ String -/-
        DCB     "[[[[[    HELLO  ERROR    ]]]]]",0 ;~~ String -/-
        DCB     "FOKKER V7 TWIN        300 PTS.",0 ;~~ String -/-
        DCB     "FOKKER EINDECKER IV   350 PTS.",0 ;~~ String -/-
        DCB     "ALBATROS DIII SCOUT   120 PTS.",0 ;~~ String -/-
        DCB     "GOTHA GIV BOMBER      500 PTS.",0 ;~~ String -/-
        DCB     "FOKKER VIII TRIPLANE  270 PTS.",0 ;~~ String -/-
        DCB     "FOKKER DE5 BIPLANE    400 PTS.",0 ;~~ String -/-
        DCB     "FOKKER V3 TRIENGINE   500 PTS.",0 ;~~ String -/-
        DCB     "CARGO AIRCRAFT        650 PTS.",0 ;~~ String -/-
        DCB     "JET FIGHTER          1000 PTS.",0 ;~~ String -/-
        DCB     "GROUND GUN DESTROYED  200 PTS.",0 ;~~ String -/-
        DCB     "GROUND BASE DESTROYE   75 PTS.",0 ;~~ String -/-
        DCB     "TANK DESTROYED        300 PTS.",0 ;~~ String -/-
        DCB     "HEADQUARTERS          400 PTS.",0 ;~~ String -/-
        DCB     "CONTROL TOWER         150 PTS.",0 ;~~ String -/-
        DCB     "PATROL BOAT           320 PTS.",0 ;~~ String -/-
        DCB     "AIRSHIP DESTROYED    1000 PTS.",0 ;~~ String -/-
        DCB     "BARRAGE BALLOON       200 PTS.",0 ;~~ String -/-
        DCB     "CONTROL TERMINAL      500 PTS.",0 ;~~ String -/-
        DCB     "OIL TANKER           1500 PTS.",0 ;~~ String -/-
        DCB     "GUN BOAT DESTROYED    800 PTS.",0 ;~~ String -/-
        DCB     "TRAIN DESTROYED       750 PTS.",0 ;~~ String -/-
        DCB     "GOTHA GIV BOMBER      500 PTS.",0 ;~~ String -/-
        DCB     "FOKKER EINDECKER I V  350 PTS.",0 ;~~ String -/-
        DCB     "FOKKER V7 TWIN        300 PTS.",0 ;~~ String -/-
        DCB     "FOKKER V3 TRIENGIN E  500 PTS.",0 ;~~ String -/-
        DCB     "CARGO AIRCRAFT        650 PTS.",0 ;~~ String -/-
        DCB     "YACHT DESTROYED       200 PTS.",0 ;~~ String -/-
        DCB     "STATION DESTROYED    1500 PTS.",0 ;~~ String -/-
        DCB     "BRIDGE DESTROYED     2000 PTS.",0 ;~~ String -/-
        DCB     "FACTORY DESTROYED     700 PTS.",0 ;~~ String -/-
        DCB     "AIRCRAFT CARRIER     6000 PTS.",0 ;~~ String -/-
        DCB     "JET FIGHTER          1000 PTS.",0 ;~~ String -/-
        DCB     " PLANE REPAIRED AND REFUELLED ",0 ;~~ String -/-
        DCB     " PLANE REPAIRED AND REFUELLED ",0 ;~~ String -/-
|CAMERAVIEWSTRINGS|
        DCB     "TIGER MOTH               PLANE",0 ;~~ String -/-
        DCB     "[[[[[     HELLO  ERROR  ]]]]]]",0 ;~~ String -/-
        DCB     "FOKKER V7 TWIN                ",0 ;~~ String -/-
        DCB     "FOKKER EINDECKER IV           ",0 ;~~ String -/-
        DCB     "ALBATROS DIII SCOUT           ",0 ;~~ String -/-
        DCB     "GOTHA GIV BOMBER              ",0 ;~~ String -/-
        DCB     "FOKKER VIII TRIPLANE          ",0 ;~~ String -/-
        DCB     "FOKKER DE5 BIPLANE            ",0 ;~~ String -/-
        DCB     "FOKKER V3 TRIENGINE           ",0 ;~~ String -/-
        DCB     "CARGO AIRCRAFT                ",0 ;~~ String -/-
        DCB     "JET FIGHTER                   ",0 ;~~ String -/-
        DCB     "GROUND GUN VIEW               ",0 ;~~ String -/-
        DCB     "GROUND BASE VIEW              ",0 ;~~ String -/-
        DCB     "TANK VIEW                     ",0 ;~~ String -/-
        DCB     "HEADQUARTERS VIEW             ",0 ;~~ String -/-
        DCB     "CONTROL TOWER VIEW            ",0 ;~~ String -/-
        DCB     "PATROL BOAT VIEW              ",0 ;~~ String -/-
        DCB     "AIRSHIP VIEW                  ",0 ;~~ String -/-
        DCB     "BARRAGE BALLOON               ",0 ;~~ String -/-
        DCB     "CONTROL TERMINAL              ",0 ;~~ String -/-
        DCB     "OIL TANKER VIEW               ",0 ;~~ String -/-
        DCB     "GUN BOAT VIEW                 ",0 ;~~ String -/-
        DCB     "TRAIN VIEW                    ",0 ;~~ String -/-
        DCB     "GOTHA GIV BOMBER              ",0 ;~~ String -/-
        DCB     "FOKKER EINDECKER IV           ",0 ;~~ String -/-
        DCB     "FOKKER V7 TWIN                ",0 ;~~ String -/-
        DCB     "FOKKER V3 TRIENGINE           ",0 ;~~ String -/-
        DCB     "CARGO AIRCRAFT                ",0 ;~~ String -/-
        DCB     "YACHT VIEW                    ",0 ;~~ String -/-
        DCB     "STATION VIEW                  ",0 ;~~ String -/-
        DCB     "BRIDGE VIEW                   ",0 ;~~ String -/-
        DCB     "FACTORY VIEW                  ",0 ;~~ String -/-
        DCB     "AIRCRAFT CARRIER              ",0 ;~~ String -/-
        DCB     "JET FIGHTER                   ",0 ;~~ String -/-
        DCB     "TRACKING CAMERA VIEW          ",0 ;~~ String -/-
        DCB     "TRACKING CAMERA VIEW          ",0 ;~~ String -/-
        DCB     "TRACKING CAMERA VIEW          ",0 ;~~ String -/-
        DCB     "PHANTOM PLANE VIEW            ",0 ;~~ String -/-
        DCB     "PLANE BULLET VIEW             ",0,0,0,0 ;~~ String -/-
|PICMAPCOORDS|
        DCD     &F8EB8000 ; AircraftCoordX
        DCD     &039D0000 ; AircraftCoordY
        DCD     &006D6000 ; AircraftCoordZ
        DCD     &00000000                       ;~ Word -/-

        DCD     &06784000                       ;~~~ Word -/-
        DCD     &0C4E0000                       ;~~ Word -/-
        DCD     &00A32000                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     &04E20000                       ;~~~ Word -/-
        DCD     &FEBE2000                       ;~~ Word -/-
        DCD     &00064000                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     &09952000                       ;~~~ Word -/-
        DCD     &FE90D000                       ;~~ Word -/-
        DCD     &00465000                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     &F5DE4000                       ;~~~ Word -/-
        DCD     &FF448000                       ;~~ Word -/-
        DCD     &005DC000                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     &F570E000                       ;~~~ Word -/-
        DCD     &040F1000                       ;~~~ Word -/-
        DCD     &00465000                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     &0007D000                       ;~~~ Word -/-
        DCD     &F3CB0000                       ;~~~ Word -/-
        DCD     &00064000                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     &F9E58000                       ;~~~ Word -/-
        DCD     &103C4000                       ;~~~ Word -/-
        DCD     &00ABE000                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     &FA642000                       ;~~~ Word -/-
        DCD     &FDB06C00                       ;~~ Word -/-
        DCD     &0007D000                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     &006D6000                       ;~~~ Word -/-
        DCD     &FFE0C000                       ;~~ Word -/-
        DCD     &00271000                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     &F9E58000                       ;~~~ Word -/-
        DCD     &0FB77000                       ;~~ Word -/-
        DCD     &00ABE000                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     &0927C000                       ;~~~ Word -/-
        DCD     &030D4000                       ;~~ Word -/-
        DCD     &00019000
        DCD     &00000000                       ;~ Word -/-

        DCD     &0B3B0000                       ;~~~ Word -/-
        DCD     &06218800                       ;~~~ Word -/-
        DCD     &001F4000                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     &FA146000                       ;~~~ Word -/-
        DCD     &030D4000                       ;~~ Word -/-
        DCD     &000FA000                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     &FD21A000                       ;~~ Word -/-
        DCD     &0C256000                       ;~~ Word -/-
        DCD     &0004B000                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     &EE4CC000                       ;~~ Word -/-
        DCD     &EE44F000                       ;~~ Word -/-
        DCD     &00032000                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     &0668A000                       ;~~~ Word -/-
        DCD     &0F2F8000                       ;~~ Word -/-
        DCD     &000FA000                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     &FBBA4000                       ;~~~ Word -/-
        DCD     &F1523000                       ;~~~ Word -/-
        DCD     &00032000                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     &07530000                       ;~~~ Word -/-
        DCD     &0C350000                       ;~~ Word -/-
        DCD     &00A0F000                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-

        DCD     &F5DE4000                       ;~~~ Word -/-
        DCD     &00A4D800                       ;~~~ Word -/-
        DCD     &001F4000                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-

|SETPLAYERINFOADDR|
        LDR     R0,|PPLAYERNUM|                  ; -> Word: &0001203C, Function entry, (alters flags)
        LDR     R0,[R0,#0] ; get player number
        ADR     R1,|ADDRESSTABLE|                  ; -> Word: &00019AA4
        ADD     R2,R1,R0,LSL #BytesPerAddressLog2 ; calc address of player's info block pointer
        LDR     R2,[R2,#0] ; get player's info pointer
        ADD     R1,R1,#&0C                      ; =12

count SETA 0
        WHILE count < 16
        LDR     R3,[R1,#4]!
        STR     R2,[R3,#0]
count SETA count + 1
        WEND

        MOV     PC,R14                          ; Function exit, Ends

|PPLAYERNUM|
        DCD     |PLAYERNUM|

|ADDRESSTABLE|
        DCD     |PLAYER1INFO|
        DCD     |PLAYER2INFO|
        DCD     |PLAYER1GHOST|
        DCD     |PLAYER1GHOST|

|STARTOFTABLE|
        DCD     |PPLAYERINFO1|
|L000087E8|
        DCD     |PPLAYERINFO2|
|L000087EC|
        DCD     |PPLAYERINFO3|
|L000087F0|
        DCD     &00000000 ; bug: isn't this a write to zero page?
|L000087F4|
        DCD     |PPLAYERINFO5|
|L000087F8|
        DCD     |PPLAYERINFO6|
|L000087FC|
        DCD     |PPLAYERINFO7|
|L00008800|
        DCD     |PPLAYERINFO8|
|L00008804|
        DCD     |PPLAYERINFO9|
|L00008808|
        DCD     |PPLAYERINFO10|
|L0000880C|
        DCD     |PPLAYERINFO11|
|L00008810|
        DCD     |PPLAYERINFO12|
|L00008814|
        DCD     |PPLAYERINFO13|
|L00008818|
        DCD     |PPLAYERINFO14|
|L0000881C|
        DCD     |RETFROMDRAWBORDERS| ; bug
|L00008820|
        DCD     |PPLAYERINFO15|
|ENDOFTABLE|

|REFINDNEARESTPLAYERCOUNTER|
        DCD     &00000000                       ; Word r/w (referenced)
|AIRCRAFTDATAARRAY5|
        DCD     MemAircraftDataArray                       ; Word r/- (referenced)
|RETFROMFINDNEARESTPLAYER|
        DCD     &00000000                       ; Word r/w (referenced)

|REFINDNEARESTPLAYER|
        LDR     R0,|REFINDNEARESTPLAYERCOUNTER|                  ; -> Word: &00000000, Function entry, (alters flags)
        ADD     R0,R0,#1
        CMP     R0,#RefindNearestPlayerInterval   ; ="d" (100)
        MOVEQ   R0,#0
        STR     R0,|REFINDNEARESTPLAYERCOUNTER|                  ; -> Word: &00000000
        MOVNE   PC,R14                          ; Function exit if NE

        STR     R14,|RETFROMFINDNEARESTPLAYER|                 ; -> Word: &00000000

        ADR     R0,|PLAYER1COORDS|                  ; -> Word array: &000FA000
        ADR     R4,|PLAYER2COORDS|                  ; -> Word array: &00177000
        LDMIA   R0,{R1-R3}
        LDMIA   R4,{R5-R7}
        LDR     R8,|AIRCRAFTDATAARRAY5|                  ; -> Word: MemAircraftDataArray
        SUB     R0,R0,#AircraftCoord                      ; =20
        SUB     R4,R4,#AircraftCoord                      ; =20

        ; Is player 1 dead?
        LDR     R9,[R0,#AircraftDamage]                   ; =56
        CMP     R9,#FatalAircraftDamage                         ; =11
        BGE     |PLAYER1DEAD|

        ; Is player 2 dead?
        LDR     R9,[R4,#AircraftDamage]                   ; =56
        CMP     R9,#FatalAircraftDamage                         ; =11
        BGE     |PLAYER2DEAD|

        B       |FINDNEARESTPLAYER|                     ; Ends

|PLAYER2DEAD|
        MOV     R5,#0
        MOV     R6,#0
        MVN     R7,#&01,4                       ; =&10000000
        STR     R7,|REFINDNEARESTPLAYERCOUNTER|                  ; -> Word: &00000000
        B       |FINDNEARESTPLAYER|                     ; Ends

|PLAYER1DEAD|
        MOV     R1,#0
        MOV     R2,#0
        MVN     R3,#&01,4                       ; =&10000000
        STR     R3,|REFINDNEARESTPLAYERCOUNTER|                  ; -> Word: &00000000
        B       |FINDNEARESTPLAYER|                     ; Ends

|FINDNEARESTPLAYER|
        MOV     R14,#(NumPracticeAircraft-1)            ; =19

|FINDNEARESTPLAYERLOOP|
        ADD     R9,R8,#AircraftCoord                      ; =20
        LDMIA   R9,{R9-R11}

        ; Find longest Manhattan distance to player 1
        XABSDIFF R9,R9,R1
        XABSDIFF R10,R10,R2
        XABSDIFF R11,R11,R3

        CMP     R9,R10
        MOVGT   R12,R9
        MOVLE   R12,R10
        CMP     R11,R12
        MOVGT   R12,R11 ; r12 is Manhattan distance to player 1

        ADD     R9,R8,#AircraftCoord                      ; =20
        LDMIA   R9,{R9-R11}

        ; Find longest Manhattan distance to player 2
        XABSDIFF R9,R9,R5
        XABSDIFF R10,R10,R6
        XABSDIFF R11,R11,R7

        CMP     R9,R10
        MOVLT   R9,R10
        CMP     R11,R9
        MOVGT   R9,R11 ; r9 is Manhattan distance to player 1

        CMP     R9,R12
        STRLT   R4,[R8,#AircraftTargetPtr]                   ; =172
        STRGE   R0,[R8,#AircraftTargetPtr]                   ; =172

        ADD     R8,R8,#BytesPerAircraft                      ; ="" (184)
        SUBS    R14,R14,#1
        BPL     |FINDNEARESTPLAYERLOOP|

        LDR     R14,|RETFROMFINDNEARESTPLAYER|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|PLAYER1INFO|
        DCD     &00000000                       ;~ Word -/-
        DCD     (3*QuarterTurn):SHL:AngleShift                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
|PLAYER1COORDS|
        DCD     &000FA000                       ; Word array r/- (referenced)
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array r/-

        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000001                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
|PLAYER1DAMAGE|
        DCD     &00000000                       ;~~~ Word array r/- (referenced)
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00023000                       ;~~~ Word array -/-
; Backup below
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     (3*QuarterTurn):SHL:AngleShift                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &000FA000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000001                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &FFFFFFF6                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00023000                       ;~~~ Word array -/-
count SETA 0
        WHILE count < 13
        DCD     &00000001                       ;~~~ Word array -/-
count SETA count + 1
        WEND

|PLAYER1KEYS|
count SETA 0
        WHILE count < 67
        DCD     &00000001                       ;~~~ Word array -/-
count SETA count + 1
        WEND

|L00008AFC|
        DCD     &009C4000                       ;~~~ Word array -/-
        DCD     &009C4000                       ;~~~ Word array -/-
        DCD     &001F4000                       ;~~~ Word array -/-

count SETA 0
        WHILE count < 14
        DCD     &00000001                       ;~~~ Word array -/-
count SETA count + 1
        WEND

|PLAYER2INFO|
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     (3*QuarterTurn):SHL:AngleShift                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
|PLAYER2COORDS|
        DCD     &00177000                       ;~~~ Word array r/- (referenced)
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000001                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
|PLAYER2DAMAGE|
        DCD     &00000000                       ;~~~ Word array r/- (referenced)
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00023000                       ;~~~ Word array -/-

; Backup below
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     (3*QuarterTurn):SHL:AngleShift                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00177000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000001                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &FFFFFFF6                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00023000                       ;~~~ Word array -/-
count SETA 0
        WHILE count < 13
        DCD     &00000001                       ;~~~ Word array -/-
count SETA count + 1
        WEND

|PLAYER2KEYS|
count SETA 0
        WHILE count < 67
        DCD     &00000001                       ;~~~ Word array -/-
count SETA count + 1
        WEND

|L00008D08|
        DCD     &009C4000                       ;~~~ Word array -/-
        DCD     &009C4000                       ;~~~ Word array -/-
        DCD     &001F4000                       ;~~~ Word array -/-

count SETA 0
        WHILE count < 14
        DCD     &00000001                       ;~~~ Word array -/-
count SETA count + 1
        WEND

|PLAYER1GHOST|
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     (3*QuarterTurn):SHL:AngleShift                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &0000A000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000001                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
|L00008D84|
        DCD     &00000000                       ;~~~ Word array r/- (referenced)
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &088B8000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     (3*QuarterTurn):SHL:AngleShift                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &0000A000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000001                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &FFFFFFF6                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &088B8000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000001                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &249F0000                       ;~~~ Word array -/-
        DCD     &249F0000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     |PLAYER1INFO|
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &0000A000                       ;~~~ Word array -/-
|PLAYER2GHOST|
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     (3*QuarterTurn):SHL:AngleShift                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &0000A000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000001                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &088B8000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     (3*QuarterTurn):SHL:AngleShift                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &0000A000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000001                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &FFFFFFF6                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &088B8000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000001                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &249F0000                       ;~~~ Word array -/-
        DCD     &249F0000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     |PLAYER2INFO|
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &0000A000                       ;~~~ Word array -/-
|NUMPLAYERS|
        DCD     &00000002                       ;~~~ Word array r/- (referenced)

|EXITGAMEIFPLAYERSDEAD|
        LDR     R0,|PLAYER1DAMAGE|                  ; -> Word array: &00000000, Function entry, (alters flags)
        CMP     R0,#ExitGameDamage                  ; =" " (32)
        MOVLT   PC,R14                          ; Function exit if LT

        LDR     R0,|NUMPLAYERS|                  ; -> Word array: &00000002
        CMP     R0,#1
        BEQ     |EXITGAME|

        LDR     R0,|PLAYER2DAMAGE|                  ; -> Word array: &00000000
        CMP     R0,#ExitGameDamage                  ; =" " (32)
        MOVLT   PC,R14                          ; Function exit if LT

        B       |EXITGAME|                     ; Ends

        ; Bug? Dead code
        LDR     R0,|L00008D84|                  ;~~ -> Word array: &00000000
        CMP     R0,#&20                         ;~~ =" " (32)
        MOVLT   PC,R14                          ;~~ Function exit if LT

        LDR     R0,|L00008D84|                  ;~~ -> Word array: &00000000
        CMP     R0,#&20                         ;~~ =" " (32)
        MOVLT   PC,R14                          ;~~ Function exit if LT

        B       |EXITGAME|                     ;~~ Ends

|RESETDEFAULTKEYSONREQ|
        MOV     R0,#ReadKey                         ; ="" (129), Function entry, (alters flags)
        MVN     R1,#KeyK                         ; ="F" (70)
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NORESETDEFAULTKEYS|

        MOV     R0,#ReadKey                         ; ="" (129)
        MVN     R1,#KeyF5                         ; ="t" (116)
        MOV     R2,#ScanKeyboard                         ; ="" (255)
        SWI     OS_Byte

        CMP     R1,#KeyIsPressed                         ; ="" (255)
        BNE     |NORESETDEFAULTKEYS|

        ADR     R0,|PLAYER1KEYSCOPY|                  ; -> Word array: &FFFFFFBE
        ADR     R1,|PLAYER1DEFAULTKEYS|                  ; -> Word array: &FFFFFF9E
        LDR     R2,|PPLAYER1KEYS|                  ; -> Word: &00019B60

        LDMIA   R1!,{R3-R12}
        STMIA   R0!,{R3-R12}
        STMIA   R2!,{R3-R12}

        LDMIA   R1!,{R3-R11}
        STMIA   R0!,{R3-R11}
        STMIA   R2!,{R3-R11}

        ADR     R0,|PLAYER2KEYSCOPY|                  ; -> Word array: &FFFFFFC5
        ADR     R1,|PLAYER2DEFAULTKEYS|                  ; -> Word array: &FFFFFFC5
        LDR     R2,|PPLAYER2KEYS|                  ; -> Word: &00019D6C

        LDMIA   R1!,{R3-R12}
        STMIA   R0!,{R3-R12}
        STMIA   R2!,{R3-R12}

        LDMIA   R1!,{R3-R11}
        STMIA   R0!,{R3-R11}
        STMIA   R2!,{R3-R11}

|NORESETDEFAULTKEYS|
        MOV     PC,R14                          ; Function exit, Ends

|PPLAYER1KEYS|
        DCD     |PLAYER1KEYS|
|PPLAYER2KEYS|
        DCD     |PLAYER2KEYS|
|PSPLITSCREEN10|
        DCD     |SPLITSCREEN|

|INITBOTHPLAYERKEYS|
        ADR     R1,|PLAYER2KEYSCOPY|                  ; -> Word array: &FFFFFFC5, Function entry, (alters flags)
        LDR     R2,|PPLAYER2KEYS|                  ; -> Word: &00019D6C
        LDMIA   R1!,{R3-R12}
        STMIA   R2!,{R3-R12}
        LDMIA   R1!,{R3-R11}
        STMIA   R2!,{R3-R11}

        LDR     R2,|PPLAYER1KEYS|                  ; -> Word: &00019B60
        LDR     R0,|PSPLITSCREEN10|                  ; -> Word: &00016B28
        LDR     R0,[R0,#0]
        CMP     R0,#0
        ADREQ   R1,|SINGLEPLAYERKEYSINIT|                  ; -> Word: &FFFFFF97
        ADRNE   R1,|PLAYER1KEYSCOPY|                  ; -> Word array: &FFFFFFBE

        LDMIA   R1!,{R3-R12}
        STMIA   R2!,{R3-R12}
        LDMIA   R1!,{R3-R11}
        STMIA   R2!,{R3-R11}

        LDR     R0,|PPLAYER1KEYS|                  ; -> Word: &00019B60
        SUB     R0,R0,#PlayerKeys            ; ="" (188)

        MOV     R1,#CamThisPlayer              ; =20
        STR     R1,[R0,#PlayerAircraftToViewB]                   ; =496

        MVN     R2,#KeyF4                         ; =20
        STR     R2,[R0,#PlayerKeyViewNextAircraft]                   ; =500

        LDR     R3,[R0,#PlayerGhostPlane]                   ; =268
        MOV     R4,#0
        STR     R4,[R3,#AircraftRoll]

        LDR     R0,|PPLAYER2KEYS|                  ; -> Word: &00019D6C
        SUB     R0,R0,#PlayerKeys           ; ="" (188)
        STR     R1,[R0,#PlayerAircraftToViewB]                   ; =496

        MVN     R2,#KeyF8                         ; ="v" (118)
        STR     R2,[R0,#PlayerKeyViewNextAircraft]                   ; =500

        LDR     R3,[R0,#PlayerGhostPlane]                   ; =268
        MOV     R4,#0
        STR     R4,[R3,#AircraftRoll]

        MOV     PC,R14                          ; Function exit, Ends

|SINGLEPLAYERKEYSINIT|
        DCD     &FFFFFF97                       ;~~ Word -/- (referenced)
        DCD     &FFFFFFB0                       ;~~ Word -/-
        DCD     &FFFFFF9E                       ;~~ Word -/-
        DCD     &FFFFFFBD                       ;~~ Word -/-
        DCD     &FFFFFFB6                       ;~~ Word -/-
        DCD     &FFFFFFFC                       ;~~ Word -/-
        DCD     &FFFFFFFB                       ;~~ Word -/-
        DCD     &FFFFFFAD                       ;~~ Word -/-
        DCD     &FFFFFF9A                       ;~~ Word -/-
        DCD     &FFFFFFF4                       ;~~ Word -/-
        DCD     &FFFFFFD5                       ;~~ Word -/-
        DCD     &FFFFFFE5                       ;~~ Word -/-
        DCD     &FFFFFF83                       ;~~ Word -/-
        DCD     &FFFFFF85                       ;~~ Word -/-
        DCD     &FFFFFFC3                       ;~~ Word -/-
        DCD     &FFFFFF8A                       ;~~ Word -/-
        DCD     &FFFFFF8B                       ;~~ Word -/-
        DCD     &FFFFFF84                       ;~~ Word -/-
        DCD     &FFFFFFE9                       ;~~ Word -/-
|PLAYER1KEYSCOPY|
        DCD     &FFFFFFBE                       ; Word array -/w (referenced)
        DCD     &FFFFFFEF                       ;~~~ Word array -/w
        DCD     &FFFFFFDD                       ;~~~ Word array -/w
        DCD     &FFFFFFCC                       ;~~~ Word array -/w
        DCD     &FFFFFFDC                       ;~~~ Word array -/w
        DCD     &FFFFFF9F                       ;~~~ Word array -/w
        DCD     &FFFFFFD2                       ;~~~ Word array -/w
        DCD     &FFFFFFBB                       ;~~~ Word array -/w
        DCD     &FFFFFFCF                       ;~~~ Word array -/w
        DCD     &FFFFFFCE                       ;~~~ Word array -/w
        DCD     &FFFFFFCA                       ;~~~ Word array -/w
        DCD     &FFFFFFBA                       ;~~~ Word array -/w
        DCD     &FFFFFFAA                       ;~~~ Word array -/w
        DCD     &FFFFFFAB                       ;~~~ Word array -/w
        DCD     &FFFFFFEA                       ;~~~ Word array -/w
        DCD     &FFFFFF8A                       ;~~~ Word array -/w
        DCD     &FFFFFF8B                       ;~~~ Word array -/w
        DCD     &FFFFFFDB                       ;~~~ Word array -/w
        DCD     &FFFFFFE9                       ;~~~ Word array -/w
|PLAYER1DEFAULTKEYS|
        DCD     &FFFFFF9E                       ;~~~ Word array r/- (referenced)
        DCD     &FFFFFFBE                       ;~~~ Word array r/-
        DCD     &FFFFFFBD                       ;~~~ Word array r/-
        DCD     &FFFFFFAD                       ;~~~ Word array r/-
        DCD     &FFFFFF9C                       ;~~~ Word array r/-
        DCD     &FFFFFFFB                       ;~~~ Word array r/-
        DCD     &FFFFFFFC                       ;~~~ Word array r/-
        DCD     &FFFFFFBB                       ;~~~ Word array r/-
        DCD     &FFFFFFCF                       ;~~~ Word array r/-
        DCD     &FFFFFFCE                       ;~~~ Word array r/-
        DCD     &FFFFFFCA                       ;~~~ Word array r/-
        DCD     &FFFFFFBA                       ;~~~ Word array r/-
        DCD     &FFFFFFAA                       ;~~~ Word array r/-
        DCD     &FFFFFFAB                       ;~~~ Word array r/-
        DCD     &FFFFFFEA                       ;~~~ Word array r/-
        DCD     &FFFFFF8A                       ;~~~ Word array r/-
        DCD     &FFFFFF8B                       ;~~~ Word array r/-
        DCD     &FFFFFFDB                       ;~~~ Word array r/-
        DCD     &FFFFFFE9                       ;~~~ Word array r/-
|PLAYER2KEYSCOPY|
        DCD     &FFFFFFC5                       ;~~~ Word array r/w (referenced)
        DCD     &FFFFFFC4                       ;~~~ Word array r/w
        DCD     &FFFFFFE4                       ;~~~ Word array r/w
        DCD     &FFFFFFD5                       ;~~~ Word array r/w
        DCD     &FFFFFFC3                       ;~~~ Word array r/w
        DCD     &FFFFFF96                       ;~~~ Word array r/w
        DCD     &FFFFFFB1                       ;~~~ Word array r/w
        DCD     &FFFFFFB3                       ;~~~ Word array r/w
        DCD     &FFFFFFA5                       ;~~~ Word array r/w
        DCD     &FFFFFFA4                       ;~~~ Word array r/w
        DCD     &FFFFFFC6                       ;~~~ Word array r/w
        DCD     &FFFFFF86                       ;~~~ Word array r/w
        DCD     &FFFFFFD6                       ;~~~ Word array r/w
        DCD     &FFFFFFE6                       ;~~~ Word array r/w
        DCD     &FFFFFFF8                       ;~~~ Word array r/w
        DCD     &FFFFFFE1                       ;~~~ Word array r/w
        DCD     &FFFFFF88                       ;~~~ Word array r/w
        DCD     &FFFFFFF9                       ;~~~ Word array r/w
        DCD     &FFFFFFE3                       ;~~~ Word array r/w
|PLAYER2DEFAULTKEYS|
        DCD     &FFFFFFC5                       ;~~~ Word array r/- (referenced)
        DCD     &FFFFFFC4                       ;~~~ Word array r/-
        DCD     &FFFFFF83                       ;~~~ Word array r/-
        DCD     &FFFFFF93                       ;~~~ Word array r/-
        DCD     &FFFFFFC3                       ;~~~ Word array r/-
        DCD     &FFFFFF94                       ;~~~ Word array r/-
        DCD     &FFFFFF85                       ;~~~ Word array r/-
        DCD     &FFFFFFB3                       ;~~~ Word array r/-
        DCD     &FFFFFFA5                       ;~~~ Word array r/-
        DCD     &FFFFFFA4                       ;~~~ Word array r/-
        DCD     &FFFFFFC6                       ;~~~ Word array r/-
        DCD     &FFFFFF86                       ;~~~ Word array r/-
        DCD     &FFFFFFD6                       ;~~~ Word array r/-
        DCD     &FFFFFFE6                       ;~~~ Word array r/-
        DCD     &FFFFFFF8                       ;~~~ Word array r/-
        DCD     &FFFFFFE1                       ;~~~ Word array r/-
        DCD     &FFFFFF88                       ;~~~ Word array r/-
        DCD     &FFFFFFF9                       ;~~~ Word array r/-
        DCD     &FFFFFFE3                       ;~~~ Word array r/-
|TAKEOFFALTITUDE|
        DCD     AircraftCentreZCoord            ;~~~ Word array r/- (referenced)
|HITLIST4|
        DCD     &00278D4                       ;~~~ Word array r/- (referenced)

|SERVICEPLAYERAIRCRAFT|
        ; r0 = aircraft pointer
        ; R1 = AircraftCtrlX
        ; R2 = AircraftCtrlY
        STR     R0,|PPLAYERINFO5|                  ; -> Word: &00019AA4, Function entry, (alters flags)
        STR     R1,|PLANEANGLEX|                  ; -> Word: &00000000
        STR     R2,|PLANEANGLEY|                  ; -> Word: &00000000
        STR     R14,|RETFROMSERVICENORMALAIRCRAFT| ; -> Word: &00000000
        LDMIA   R0,{R1-R5} ; load aircraft attitude and R5=speed
        STR     R5,|AIRCRAFTSPEED|                  ; -> Word: &00000000

        MOV     R14,#0
        CMP     R1,#QuarterTurn:SHL:AngleShift                      ; =&168000
        MOVGT   R14,#1

        LDR     R6,|THREEQUARTERTURN6|                  ; -> Word: &00438000
        CMP     R1,R6
        MOVGT   R14,#0
        STR     R14,|AIRCRAFTISUPSIDEDOWN|                 ; -> Word: &00000000

        ; Consume fuel at a rate proportionate to the throttle setting
        LDR     R6,[R0,#AircraftThrottle]                   ; =48
        LDR     R7,[R0,#AircraftFuel]                   ; =1<<6
        SUB     R7,R7,R6,ASR #ThrottleToFuelLog2
        CMP     R7,#0
        MOVLT   R7,#0
        STR     R7,[R0,#AircraftFuel]                   ; =1<<6

        ; Adjust speed for friction and thrust
        SUB     R5,R5,R5,ASR #FrictionLog2
        ADDGT   R5,R5,R6,LSL #ThrottleToThrustLog2

        LDR     R12,[R0,#AircraftUnknown]                  ; =52

        LDR     R8,[R0,#AircraftDamage]                   ; =56
        CMP     R8,#(FatalAircraftDamage-1)                      ; =10
        MOVGT   R7,#0 ; close throttle: player is shot down
        STRGT   R7,[R0,#AircraftThrottle]                   ; =48
        STRGT   R7,[R0,#AircraftFireGun]                   ; =32
        MOVGT   R7,R5 ; stash speed
        MOVGT   R5,#&05,20                      ; =&5000
        BGT     |L00009228|

        CMP     R5,#&29,22                      ; =&A400
        BGT     |L0000923C|

|L00009228|
        RSB     R10,R5,#&29,22                  ; =&A400
        LDR     R14,|AIRCRAFTISUPSIDEDOWN|                 ; -> Word: &00000000
        CMP     R14,#0
        ADDEQ   R12,R12,R10,ASR #7
        SUBNE   R12,R12,R10,ASR #7

|L0000923C|
        CMP     R8,#(FatalAircraftDamage-1)                      ; =10
        MOVGT   R5,R7 ; restore speed
        CMP     R12,#&02,22                     ; =&800
        MOVGT   R12,#&02,22                     ; =&800
        CMN     R12,#&02,22                     ; =&800
        MVNLT   R12,#&02,22                     ; =&800
        SUB     R12,R12,R12,ASR #AircraftUnknownDecayLog2
        STR     R12,[R0,#AircraftUnknown]                  ; =52

        XABS    R12
        MOV     R12,R12,ASR #1 ; abs(AircraftUnknown)/2
        RSB     R12,R12,#AircraftUnknownMax/2     ; =&1000
        CMP     R12,#&C8                        ; ="" (200)
        MOVLT   R12,#&C8                        ; ="" (200)

        LDR     R6,|PLANEANGLEX|                  ; -> Word: &00000000
        MUL     R7,R6,R12
        MOV     R6,R7,ASR #12
        STR     R6,|PLANEANGLEX|                  ; -> Word: &00000000

        LDR     R6,|PLANEANGLEY|                  ; -> Word: &00000000
        MUL     R7,R6,R12
        MOV     R6,R7,ASR #12
        STR     R6,|PLANEANGLEY|                  ; -> Word: &00000000

        LDR     R12,[R0,#AircraftCoordZ]  ; bug?      ; =28

        CMP     R8,#(FatalAircraftDamage-1)                      ; =10
        MOVGT   R6,#&C8                         ; ="" (200)
        STRGT   R6,|PLANEANGLEX|                  ; -> Word: &00000000
        MOVGT   R6,#&1E                         ; =30
        STRGT   R6,|PLANEANGLEY|                  ; -> Word: &00000000

        LDR     R8,[R0,#AircraftDamage]                   ; =56
        CMP     R8,#FatalAircraftDamage                         ; =11
        BNE     |NOTSMOKING2|

        LDR     R12,|PTMPSTORE|                 ; -> Word: &0001898C
        STMIA   R12,{R0-R12}

        LDR     R2,[R0,#AircraftCoordZ]                   ; =28
        CMP     R2,#AircraftCentreZCoord               ; =&A000
        MOVEQ   R3,#CrashDamage                 ; =13
        STREQ   R3,[R0,#AircraftDamage]                   ; =56

        LDR     R2,[R0,#AircraftSpeed]                   ; =16
        CMP     R2,#&64                         ; ="d" (100)
        MOVLT   R3,#CrashDamage                 ; =13
        STRLT   R3,[R0,#AircraftDamage]                   ; =56

        LDR     R2,[R0,#AircraftCoordX]                   ; =20
        LDR     R3,[R0,#AircraftCoordY]                   ; =24
        LDR     R4,[R0,#AircraftCoordZ]                   ; =28
        MOV     R5,#SmokeTypeQuickBlack
        BL      |ADDSMOKEGEN|

        LDR     R12,|PTMPSTORE|                 ; -> Word: &0001898C
        LDMIA   R12,{R0-R12}
|NOTSMOKING2|
        ; R3 = AircraftRoll
        MOV     R6,R3,ASR #AngleShift
        BIC     R6,R6,#AngleStepMask
        LDR     R7,|COSINE6|                  ; -> Word: MemCosine
        LDR     R8,|SINE6|                  ; -> Word: MemSine
        LDR     R11,[R7,R6] ; get cosine(AircraftRoll)
        LDR     R12,[R8,R6] ; get sine(AircraftRoll)

        CMP     R5,#&0A,22                      ; =&2800
        MOVLE   R6,#0
        LDRGT   R6,|PLANEANGLEX|                  ; -> Word: &00000000

        ADD     R3,R3,R6,LSL #10 ; Adjust AircraftRoll
        LDRGT   R6,|PLANEANGLEY|                  ; -> Word: &00000000

        ADD     R6,R6,R6,ASR #2
        MUL     R10,R6,R11
        ADD     R1,R1,R10,ASR #3 ; Adjust AircraftPitch

        MUL     R10,R6,R12

        LDR     R14,|AIRCRAFTISUPSIDEDOWN|                 ; -> Word: &00000000
        CMP     R14,#1
        BEQ     |L0000935C|

        ADD     R2,R2,R10,ASR #3 ; Adjust AircraftHeading

        CMP     R12,#0
        ADDGT   R1,R1,R12,LSL #1 ; Adjust AircraftPitch
        SUBLE   R1,R1,R12,LSL #1

        SUB     R2,R2,R12,LSL #2 ; Adjust AircraftHeading
        B       |L00009370|                     ; Ends

|L0000935C|
        SUB     R2,R2,R10,ASR #3 ; Adjust AircraftHeading

        CMP     R12,#0
        SUBGT   R1,R1,R12,LSL #1 ; Adjust AircraftPitch
        ADDLE   R1,R1,R12,LSL #1

        ADD     R2,R2,R12,LSL #2 ; Adjust AircraftHeading

|L00009370|
        LDR     R14,[R0,#PlayerMinZCoord]                  ; =184
        LDR     R10,[R0,#AircraftCoordZ]                  ; =28
        CMP     R10,R14
        MOVGT   R6,R4,ASR #AngleShift
        BICGT   R6,R6,#AngleStepMask
        LDRGT   R11,[R8,R6]
        ADDGT   R5,R5,R11,ASR #1

        LDR     R8,[R0,#AircraftDamage]                   ; =56
        CMP     R8,#FatalAircraftDamage                         ; =11
        BLE     |PLAYERNOTDEAD|

        ; An aircraft was shot down
        ADD     R8,R8,#1
        CMP     R8,#MaxAircraftDamage                     ; ="#" (35)
        BGT     |REVIVEPLAYERIFPRACTICE|

        STR     R8,[R0,#AircraftDamage]                   ; =56
        CMP     R8,#ExplodedAircraftDamage         ; =20
        MOV     R1,#HalfTurn:SHL:AngleShift                      ; =&2D0000
        MOV     R3,#0
        BGT     |PLAYERALREADYEXPLODED|

        ; An aircraft was destroyed
        LDR     R12,|PTMPSTORE|                 ; -> Word: &0001898C
        STMIA   R12,{R0-R12}

        LDR     R1,|PPLAYERINFO6| ; bug: unused
        CMP     R8,#FatalAircraftDamage ; bug?

        MOV     R8,#ExplodedAircraftDamage    ; =20
        STR     R8,[R0,#AircraftDamage]                   ; =56

        LDR     R8,[R0,#AircraftType]                   ; =140
        CMP     R8,#ATYPE_GOTHA_G_IV_BOMBER
        MOVEQ   R5,#ExplosionStyleSmall                         ; ="c" (99)
        MOVNE   R5,#ExplosionStyleMedium

        LDR     R2,[R0,#AircraftCoordX]                   ; =20
        LDR     R3,[R0,#AircraftCoordY]                   ; =24
        LDR     R4,[R0,#AircraftCoordZ]                   ; =28
        BL      |ADDEXPLOSION|

        LDR     R2,[R0,#AircraftType]                   ; =140
        LDR     R1,|HITLIST4|                  ; -> Word array: MemHitList
        LDRB    R3,[R1,R2]
        ADD     R3,R3,#1
        STRB    R3,[R1,R2]

        LDR     R12,|PTMPSTORE|                 ; -> Word: &0001898C
        LDMIA   R12,{R0-R12}
|PLAYERALREADYEXPLODED|
        MOV     R12,#0
        STR     R12,[R0,#AircraftUnknown]                  ; =52

        MOV     R5,#CrashingAircraftSpeed               ; =11

|PLAYERNOTDEAD|
        LDR     R14,[R0,#PlayerMinZCoord]                  ; =184
        LDR     R10,[R0,#AircraftCoordZ]                  ; =28
        CMP     R10,R14
        BGT     |PLAYERNOTLANDED|

        LDR     R10,[R0,#AircraftDamage]                  ; =56
        CMP     R10,#FatalAircraftDamage                        ; =11
        BGT     |PLAYERNOTLANDED|

        ; Player has landed
        CMP     R5,#10
        LDRGT   R10,|PLANEANGLEX|                 ; -> Word: &00000000
        SUBGT   R2,R2,R10,LSL #9

        SUB     R5,R5,#&4B,30                   ; =&12C

        ; Check whether the player landed on a carrier
        CMP     R14,#AircraftCentreZCoord              ; =&A000
        BEQ     |MISSEDARRESTORHOOK|

        ; Check aircraft's position relative to the carrier deck
        LDR     R14,[R0,#AircraftCoordX]                  ; =20
        SUB     R14,R14,#&AF,20                 ; =&AF000
        XABS    R14
        CMP     R14,#&19,20                     ; =&19000
        BGT     |MISSEDARRESTORHOOK| ; Missed arrestor hook

        ; Caught arrestor hook
        LDR     R14,[R0,#AircraftThrottle]                  ; =48
        CMP     R14,#0
        BNE     |MISSEDARRESTORHOOK| ; Throttle not closed

        CMP     R5,#MinSpeedForArrestorHook     ; =&2800
        BLT     |MISSEDARRESTORHOOK| ; Already slow enough

        ; Rapid slowdown on carrier deck
        SUB     R5,R5,#SpeedLossFromArrestorHook   ; =&6400

        ; Adjust AircraftPitch for arrestor hook
        LDR     R14,|AIRCRAFTISUPSIDEDOWN|                 ; -> Word: &00000000
        CMP     R14,#1
        SUBEQ   R1,R1,#ArrestorHookRotStep:SHL:AngleShift    ; =&20000
        ADDNE   R1,R1,#ArrestorHookRotStep:SHL:AngleShift    ; =&20000

|MISSEDARRESTORHOOK|
        CMP     R5,#0
        MOVLT   R5,#0 ; minimum speed is 0

        LDR     R14,|AIRCRAFTISUPSIDEDOWN|                 ; -> Word: &00000000
        CMP     R14,#1
        MOVNE   R3,#0 ; set AircraftRoll
        MOVEQ   R3,#HalfTurn:SHL:AngleShift                      ; =&2D0000
        BEQ     |UPSIDEDOWNCLAMPPITCH|

        CMP     R1,#TwentyDegrees:SHL:AngleShift                   ; =&50000
        BLT     |L000094B8| ; too little AircraftPitch

        CMP     R1,#HalfTurn:SHL:AngleShift                      ; =&2D0000
        MOVLT   R1,#TwentyDegrees:SHL:AngleShift                   ; =&50000
|L000094B8|
        LDR     R10,|NEARESTFULLROT|                 ; -> Word: &00550000
        CMP     R1,R10 ; check AircraftPitch
        BGT     |L000094E8|

        CMP     R1,#HalfTurn:SHL:AngleShift                      ; =&2D0000
        MOVGT   R1,R10 ; maximum AircraftPitch
        B       |L000094E8|                     ; Ends

|UPSIDEDOWNCLAMPPITCH|
        LDR     R14,|MAXPITCH|                 ; -> Word: &00320000
        CMP     R1,R14
        MOVGT   R1,R14 ; maximum AircraftPitch

        LDR     R14,|MINPITCH|                 ; -> Word: &00280000
        CMP     R1,R14 ; minimum AircraftPitch
        MOVLT   R1,R14
|L000094E8|
        CMP     R5,#&0A,22                      ; =&2800
        BLT     |L00009518|

        LDR     R14,|AIRCRAFTISUPSIDEDOWN|                 ; -> Word: &00000000
        CMP     R14,#1
        BEQ     |L00009510|

        MOV     R14,R1
        CMP     R1,#HalfTurn:SHL:AngleShift                      ; =&2D0000
        SUBGT   R14,R1,#FullRotation:SHL:AngleShift                  ; =&5A0000
        SUB     R1,R1,R14,ASR #2 ; change AircraftPitch
        B       |L00009518|                     ; Ends

|L00009510|
        RSB     R14,R1,#HalfTurn:SHL:AngleShift                  ; =&2D0000
        ADD     R1,R1,R14,ASR #2 ; change AircraftPitch
|L00009518|
        CMP     R5,#&29,22                      ; =&A400
        BGT     |PLAYERNOTLANDED|

        LDR     R14,|AIRCRAFTISUPSIDEDOWN|                 ; -> Word: &00000000
        CMP     R14,#1
        MOVNE   R14,#&01,20                     ; =&1000
        MVNEQ   R14,#&01,20                     ; =&1000

        CMP     R5,#&0A,22                      ; =&2800
        ADDLT   R1,R1,R14 ; change AircraftPitch
        BLT     |L00009584|

        CMP     R5,#&06,20                      ; =&6000
        BGT     |L00009584|

        LDR     R14,|AIRCRAFTISUPSIDEDOWN|                 ; -> Word: &00000000
        CMP     R14,#1
        BEQ     |L00009570|

        MOV     R14,R1
        CMP     R1,#HalfTurn:SHL:AngleShift                      ; =&2D0000
        SUBGT   R14,R1,#FullRotation:SHL:AngleShift                  ; =&5A0000
        SUB     R1,R1,R14,ASR #1
        ADD     R1,R1,#UnknownAngle:SHL:AngleShift             ; =&8000

        MOV     R14,#0
        STR     R14,[R0,#AircraftUnknown]                  ; =52

        B       |L00009584|                     ; Ends

|L00009570|
        RSB     R14,R1,#HalfTurn:SHL:AngleShift                  ; =&2D0000
        ADD     R1,R1,R14,ASR #1
        SUB     R1,R1,#UnknownAngle:SHL:AngleShift             ; =&8000

        MOV     R14,#0
        STR     R14,[R0,#AircraftUnknown]                  ; =52

|L00009584|
        LDR     R10,[R0,#AircraftUnknown]                  ; =52
        LDR     R14,|AIRCRAFTISUPSIDEDOWN|                 ; -> Word: &00000000
        CMP     R14,#1
        RSB     R11,R5,#&29,22                  ; =&A400
        SUBNE   R10,R10,R11,ASR #7
        ADDEQ   R10,R10,R11,ASR #7

        CMP     R5,#MaxRefuellingSpeed                     ; =10
        BGT     |NOREFUELORREPAIR|

        LDR     R11,[R0,#AircraftDamage]                  ; =56
        CMP     R11,#FatalAircraftDamage                        ; =11
        BGE     |NOREFUELORREPAIR|

        ; Refill the fuel tank gradually
        LDR     R11,[R0,#AircraftFuel]                  ; =1<<6
        LDR     R12,|MAXFUEL|                 ; -> Word: &000222E0
        ADD     R11,R11,#FuelIncrement        ; =&400
        CMP     R11,R12
        MOVGT   R11,R12
        STR     R11,[R0,#AircraftFuel]                  ; =1<<6

        MOVGT   R12,#MsgRepairedRefuelled
        STRGT   R12,[R0,#AircraftMsgNum]                  ; =180
        MOVGT   R12,#MsgPeriodRepairedRefuelled
        STRGT   R12,[R0,#AircraftMsgRemain]                  ; =176

        ; Repair the aircraft gradually
        LDR     R11,[R0,#AircraftDamage]                  ; =56
        SUB     R11,R11,#DamageRepairRate
        CMN     R11,#NegMinAircraftDamage                    ; =10
        MVNLT   R11,#(NegMinAircraftDamage-1)
        STR     R11,[R0,#AircraftDamage]                  ; =56

        ; bug: redundant branch
        B       |NOREFUELORREPAIR|                     ; Ends

|NOREFUELORREPAIR|
        STR     R10,[R0,#AircraftUnknown]                  ; =52
|PLAYERNOTLANDED|
        ; R5 = new speed
        LDR     R11,|AIRCRAFTSPEED|                 ; -> Word: &00000000
        ADD     R5,R5,R11
        MOV     R5,R5,ASR #1 ; mean of old and new speed

        LDR     R10,[R0,#AircraftUnknown]                  ; =52
        ADD     R1,R1,R10,LSL #6 ; Adjust AircraftPitch
        MOV     R4,R1 ; assign AircraftPitch to AircraftAngleW
        ADD     R4,R4,R10,LSL #9 ; Adjust AircraftAngleW

        CMP     R5,#&06,20                      ; =&6000
        BGT     |TOOFASTORAIRBORNE2|

        LDR     R10,[R0,#AircraftCoordZ]                  ; =28
        LDR     R14,[R0,#PlayerMinZCoord]                  ; =184
        CMP     R10,R14
        BNE     |TOOFASTORAIRBORNE2|

        ; Adjust AircraftAngleW when slow on the ground
        LDR     R14,|AIRCRAFTISUPSIDEDOWN|                 ; -> Word: &00000000
        CMP     R14,#0
        MOVEQ   R4,#UnknownAngle:SHL:AngleShift                ; =&8000
        MOVNE   R4,#HalfTurn:SHL:AngleShift                      ; =&2D0000
        SUBNE   R4,R4,#UnknownAngle:SHL:AngleShift             ; =&8000

|TOOFASTORAIRBORNE2|
        CMP     R1,#0 ; AircraftPitch
        ADDLT   R1,R1,#FullRotation:SHL:AngleShift   ; =&5A0000
        CMP     R1,#FullRotation:SHL:AngleShift      ; =&5A0000
        SUBGT   R1,R1,#FullRotation:SHL:AngleShift   ; =&5A0000

        CMP     R2,#0 ; AircraftHeading
        ADDLT   R2,R2,#FullRotation:SHL:AngleShift   ; =&5A0000
        CMP     R2,#FullRotation:SHL:AngleShift      ; =&5A0000
        SUBGT   R2,R2,#FullRotation:SHL:AngleShift   ; =&5A0000

        CMP     R3,#0 ; AircraftRoll
        ADDLT   R3,R3,#FullRotation:SHL:AngleShift   ; =&5A0000
        CMP     R3,#FullRotation:SHL:AngleShift      ; =&5A0000
        SUBGT   R3,R3,#FullRotation:SHL:AngleShift   ; =&5A0000

        CMP     R4,#0 ; AircraftAngleW
        ADDLT   R4,R4,#FullRotation:SHL:AngleShift   ; =&5A0000
        CMP     R4,#FullRotation:SHL:AngleShift      ; =&5A0000
        SUBGT   R4,R4,#FullRotation:SHL:AngleShift   ; =&5A0000

        STMIA   R0,{R1-R5} ; store aircraft attitude and speed

|FINISHEDSERVICEPLAYER|
        LDR     R14,|RETFROMSERVICENORMALAIRCRAFT| ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|RETFROMSERVICENORMALAIRCRAFT|
        DCD     &00000000                       ; Word r/w (referenced)
|PPLAYERINFO5|
        DCD     |PLAYER1INFO|
|PLANEANGLEX|
        DCD     &00000000                       ; Word r/w (referenced)
|PLANEANGLEY|
        DCD     &00000000                       ; Word r/w (referenced)
|COSINE6|
        DCD     MemCosine                       ; Word r/- (referenced)
|SINE6|
        DCD     MemSine                       ; Word r/- (referenced)
|THREEQUARTERTURN6|
        DCD     (3*QuarterTurn):SHL:AngleShift                       ; Word r/- (referenced)
|AIRCRAFTSPEED|
        DCD     &00000000                       ; Word r/w (referenced)
|NEARESTFULLROT|
        DCD     NearestFullRot:SHL:AngleShift      ; Word r/- (referenced)
        DCD     &00000000                       ;~ Word -/-
|MAXFUEL|
        DCD     &000222E0                       ; Word r/- (referenced)
|PTMPSTORE|
        DCD     |TMP|
|MAXPITCH|
        DCD     &00320000                       ; Word r/- (referenced)
|MINPITCH|
        DCD     &00280000                       ; Word r/- (referenced)
|PPLAYERINFO6|
        DCD     |PLAYER1INFO|
|AIRCRAFTISUPSIDEDOWN|
        DCD     &00000000                       ; Word r/w (referenced)
|P4PREVENTTIMESKIP|
        DCD     |PREVENTTIMESKIP|
|PRACTICEADDR4|
        DCD     |ISPRACTICEMISSION|

|REVIVEPLAYERIFPRACTICE|
        LDR     R12,|PRACTICEADDR4|                 ; -> Word: &00011FC8
        LDR     R12,[R12,#0]
        CMP     R12,#0
        BEQ     |FINISHEDSERVICEPLAYER| ; not a practice mission

        LDR     R12,[R0,#AircraftScore]                  ; =60
        ADD     R12,R12,#ScorePerAircraftRevival         ; ="d" (100)
        ADD     R1,R0,#AircraftBackup                      ; ="D" (68)
        LDMIA   R1!,{R2-R11}
        STMIA   R0!,{R2-R11}
        LDMIA   R1!,{R2-R8}
        STMIA   R0!,{R2-R8}
        STR     R12,[R0,#(AircraftScore-AircraftBackup)]
        B       |FINISHEDSERVICEPLAYER|                     ; Ends

|REVIVEAIRCRAFTIFPRACTICE|
        LDR     R12,|PRACTICEADDR4|                 ; -> Word: &00011FC8
        LDR     R12,[R12,#0]
        CMP     R12,#0
        BEQ     |FINISHEDAIRCRAFT| ; not a practice mission

        LDR     R12,[R0,#AircraftScore]                  ; =60
        ADD     R12,R12,#ScorePerAircraftRevival         ; ="d" (100)
        ADD     R1,R0,#AircraftBackup                      ; ="D" (68)
        LDMIA   R1!,{R2-R11}
        STMIA   R0!,{R2-R11}
        LDMIA   R1!,{R2-R8}
        STMIA   R0!,{R2-R8}
        STR     R12,[R0,#(AircraftScore-AircraftBackup)]
        B       |FINISHEDAIRCRAFT|                     ; Ends

|PAIRCRAFTTOCAMERAVEC4|
        DCD     |AIRCRAFTTOCAMERAVEC|
|FRAMEBUFFER8|
        DCD     |FRAMEBUFFER|
|P2FRAMEBUFFER2|
        DCD     |FRAMEBUFFER2|
|PFRAMEBUFFERCOPY3|
        DCD     |FRAMEBUFFERCOPY|
|SCREENOFFSET3|
        DCD     (128*RowStride)+DASHBOARDWIDTH                  ; Word r/- (referenced)
|RETURNADDR18|
        DCD     &00000000                       ; Word r/w (referenced)
|UNKNOWNBOOLADDR4|
        DCD     |L000059BC|
|PPLAYER2INFO16|
        DCD     |PLAYER2INFO|
|PRACTICEADDR5|
        DCD     |ISPRACTICEMISSION|
|PPLAYERNUM5|
        DCD     |PLAYERNUM|
|PTIMEWARPCOUNTDOWN2|
        DCD     |TIMEWARPCOUNTDOWN|
|PPLAYER1INFO18|
        DCD     |PLAYER1INFO|

|DOSERIALGAME|
        STR     R14,|RETURNADDR18|                 ; -> Word: &00000000, Function entry, (alters flags)
        BL      |DRAWBORDER|

        MOV     R0,#0 ; bug? unused
        BL      |PERIODICALLYDRAWGAUGES|

        LDR     R12,|PPLAYER2INFO16|                 ; -> Word: &00019CB0
        BL      |SERVICEGHOSTPLANE|

        LDR     R0,|SCREENOFFSET3|                  ; -> Word: &0000A050

        LDR     R1,|FRAMEBUFFER8|                  ; -> Word: &0001204C
        LDR     R2,[R1,#0]
        ADD     R2,R2,R0
        STR     R2,[R1,#0]

        LDR     R1,|P2FRAMEBUFFER2|                  ; -> Word: &00013700
        LDR     R2,[R1,#0]
        ADD     R2,R2,R0
        STR     R2,[R1,#0]

        LDR     R1,|PFRAMEBUFFERCOPY3|                  ; -> Word: &00014C38
        LDR     R2,[R1,#0]
        ADD     R2,R2,R0
        STR     R2,[R1,#0]

        LDR     R0,|PTIMEWARPCOUNTDOWN2|                  ; -> Word: &000113E0
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BGT     |SKIPUPDATEFORTIMEWARP|

        LDR     R0,|PAIRCRAFTTOCAMERAVEC4|                  ; -> Word: &00018B88
        MOV     R1,#0
        MOV     R2,#0
        MOV     R3,#0
        STMIA   R0,{R1-R3} ; zero movement vector

        MOV     R0,#1
        LDR     R1,|PPLAYERNUM5|                  ; -> Word: &0001203C
        STR     R0,[R1,#0]

        BL      |SETPLAYERINFOADDR|

        LDR     R1,|PPLAYER2INFO16|                  ; -> Word: &00019CB0
        LDR     R1,[R1,#AircraftViewMap]                   ; =168
        CMP     R1,#0
        BNE     |DRAWSCORES| ; no crosshair or explosion update in map

        LDR     R0,|UNKNOWNBOOLADDR4|                  ; -> Word: &00016B2C
        MOV     R1,#1
        STR     R1,[R0,#0]

        BL      |SETVIEWIFDEAD|

        LDR     R1,|PPLAYER2INFO16|                  ; -> Word: &00019CB0
        LDR     R1,[R1,#PlayerAircraftToViewPtr]                   ; =272
        LDR     R1,[R1,#AircraftViewIn]                   ; =44
        CMP     R1,#ViewOutside
        BLEQ    |UPDATEEXTERNALCAM|

        BL      |INITOBJMESHADDR|

        LDR     R0,|PDOGFIGHT4|                  ; -> Word: &00016C38
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BNE     |ISDOGFIGHT2|

        BL      |MOVETARGETS|
        BL      |DRAWALLAIRCRAFT|

|ISDOGFIGHT2|
        BL      |DRAWAIRCRAFTVIEWFORPLAYER1|

        LDR     R10,|PPLAYER1INFO18|                 ; -> Word: &00019AA4
        BL      |DRAWAIRCRAFTVIEWFORPLAYER|

        LDR     R0,|PPLAYER2INFO16|                  ; -> Word: &00019CB0
        BL      |DRAWSCENEFORPLAYER|

        BL      |SERVICEPLAYERBULLETS|

        LDR     R0,|PRACTICEADDR5|                  ; -> Word: &00011FC8
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BLEQ    |SERVICEENEMYBULLETS|

        BL      |SERVICESMOKE|
        BL      |SERVICEEXPLOSIONS|

        LDR     R0,|PPLAYER2INFO16|                  ; -> Word: &00019CB0
        LDR     R1,[R0,#PlayerAircraftToView]                   ; =264
        CMP     R1,#CamThisPlayer                         ; =20
        BNE     |NOTINSIDEFRONTVIEW|

        LDR     R1,[R0,#AircraftViewIn]                   ; =44
        CMP     R1,#ViewInside
        BNE     |NOTINSIDEFRONTVIEW|

        LDR     R1,[R0,#AircraftViewQuarter]                   ; =36
        CMP     R1,#QuarterFront
        BNE     |NOTINSIDEFRONTVIEW|

        BL      |DRAWCROSSHAIR|

|NOTINSIDEFRONTVIEW|
        BL      |DISPLAYDEMO|
        BL      |DISPLAYMSG|

|DRAWSCORES|
        LDR     R1,|PPLAYER1INFO18|                  ; -> Word: &00019AA4
        LDR     R1,[R1,#AircraftScore]                   ; =60
        LDR     R0,|FRAMEBUFFER9|                  ; -> Word: &0001204C
        LDR     R0,[R0,#0]
        LDR     R2,|P1SCOREOFFSET|                  ; -> Word: &FFFFF6A2
        ADD     R0,R0,R2
        BL      |DRAWSCORE|

        LDR     R1,|PPLAYER1INFO18| ; bug: should be player 2? -> Word: &00019AA4
        LDR     R1,[R1,#AircraftScore]                   ; =60
        LDR     R0,|FRAMEBUFFER9|                  ; -> Word: &0001204C
        LDR     R0,[R0,#0]
        LDR     R2,|P2SCOREOFFSET|                  ; -> Word: &000095B2
        ADD     R0,R0,R2
        BL      |DRAWSCORE|

        LDR     R1,|PPLAYER1INFO18|                  ; -> Word: &00019AA4
        LDR     R1,[R1,#AircraftDamage]                   ; =56
        LDR     R0,|FRAMEBUFFER9|                  ; -> Word: &0001204C
        LDR     R0,[R0,#0]
        LDR     R2,|P1DAMAGEOFFSET|                  ; -> Word: &FFFFD13A
        ADD     R0,R0,R2
        BL      |DRAWDAMAGE|

        LDR     R1,|PPLAYER2INFO16|                  ; -> Word: &00019CB0
        LDR     R1,[R1,#AircraftDamage]                   ; =56
        LDR     R0,|FRAMEBUFFER9|                  ; -> Word: &0001204C
        LDR     R0,[R0,#0]
        LDR     R2,|P2DAMAGEOFFSET|                  ; -> Word: &00007048
        ADD     R0,R0,R2
        BL      |DRAWDAMAGE|

|SKIPUPDATEFORTIMEWARP|
        LDR     R0,|PPLAYER1INFO18|                  ; -> Word: &00019AA4
        MOV     R1,#0
        STR     R1,[R0,#AircraftSerialBitMask]                   ; =152

        LDR     R0,|PPLAYER2INFO16|                  ; -> Word: &00019CB0
        STR     R1,[R0,#AircraftSerialBitMask]                   ; =152

        LDR     R0,|UNKNOWNBOOLADDR4|                  ; -> Word: &00016B2C
        MOV     R1,#0
        STR     R1,[R0,#0]
        BL      |DRAWBORDER|

        MOV     R0,#1 ; bug? unused
        BL      |PERIODICALLYDRAWGAUGES| ; bug? Already did this

        BL      |RESETDEFAULTKEYSONREQ|

        LDR     R14,|RETURNADDR18|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|PDOGFIGHT4|
        DCD     |DOGFIGHT|
|FRAMEBUFFER9|
        DCD     |FRAMEBUFFER|
|P1SCOREOFFSET|
        DCD     &FFFFF6A2                       ; Word r/- (referenced)
|P2SCOREOFFSET|
        DCD     (119*RowStride)+242                 ; Word r/- (referenced)
|P1DAMAGEOFFSET|
        DCD     &FFFFD13A                       ; Word r/- (referenced)
|P2DAMAGEOFFSET|
        DCD     (89*RowStride)+264                  ; Word r/- (referenced)
|FRAMEBUFFER10|
        DCD     |FRAMEBUFFER|
|L00009960|
        DCD     &00009C40                       ; Word r/- (referenced)
|BORDERPIXELDATA|
        DCD     &00000000                       ; Word array r/- (referenced)
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-

|DRAWBORDER|
        MOV     R0,#0                           ; Function entry, (alters flags)
        LDR     R1,|FRAMEBUFFER10|                  ; -> Word: &0001204C
        LDR     R1,[R1,#0]
        ADD     R1,R1,#RowStride                   ; =&140
        ADD     R2,R1,#&EE                      ; ="" (238)
        MOV     R3,#(SPLITHEIGHT-3)                         ; ="}" (125)
|DRAWBORDERLOOP|
        STRB    R0,[R1,#0]
        STRB    R0,[R1,#-1]
        STRB    R0,[R2,#0]
        STRB    R0,[R2,#1]
        ADD     R1,R1,#RowStride                   ; =&140
        ADD     R2,R2,#RowStride                   ; =&140
        SUBS    R3,R3,#1
        BPL     |DRAWBORDERLOOP|

        ADR     R1,|BORDERPIXELDATA|                  ; -> Word array: &00000000
        LDMIA   R1,{R1-R10}

        LDR     R0,|FRAMEBUFFER10|                  ; -> Word: &0001204C
        LDR     R0,[R0,#0]

count SETA 0
        WHILE count < (WIDTH-DASHBOARDWIDTH)/PixelCopyChunk
        STMIA   R0!,{R1-R10}
count SETA count + 1
        WEND

        ADD     R0,R0,#DASHBOARDWIDTH                      ; ="P" (80)
count SETA 0
        WHILE count < (WIDTH-DASHBOARDWIDTH)/PixelCopyChunk
        STMIA   R0!,{R1-R10}
count SETA count + 1
        WEND

        LDR     R0,|FRAMEBUFFER10|                  ; -> Word: &0001204C
        LDR     R0,[R0,#0]
        LDR     R11,|L00009960|                 ; -> Word: &00009C40
        ADD     R0,R0,R11

count SETA 0
        WHILE count < (WIDTH-DASHBOARDWIDTH)/PixelCopyChunk
        STMIA   R0!,{R1-R10}
count SETA count + 1
        WEND

        ADD     R0,R0,#DASHBOARDWIDTH                      ; ="P" (80)

count SETA 0
        WHILE count < (WIDTH-DASHBOARDWIDTH)/PixelCopyChunk
        STMIA   R0!,{R1-R10}
count SETA count + 1
        WEND

        MOV     PC,R14                          ; Function exit, Ends

|FRAMEBUFFER11|
        DCD     |FRAMEBUFFER|
|FBOFFSETA|
        DCD     -12339                       ; Word r/- (referenced)
|FBOFFSETB|
        DCD     -12660                       ; Word r/- (referenced)
|RETFROMPERIODICALLYDRAWGAUGES|
        DCD     &00000000                       ; Word r/w (referenced)
|FRAMEBUFFER11RESTORECOPY|
        DCD     &00000000                       ; Word r/w (referenced)

|PERIODICALLYDRAWGAUGES|
        LDR     R0,|PTIMEWARPCOUNTDOWN2|                  ; -> Word: &000113E0, Function entry, (alters flags)
        LDR     R0,[R0,#0]
        CMP     R0,#0
        MOVGT   PC,R14                          ; Function exit if GT

        STR     R14,|RETFROMPERIODICALLYDRAWGAUGES|                 ; -> Word: &00000000

        CMP     R0,#0 ; bug? it seems to always be 0
        LDR     R0,|FRAMEBUFFER11|                  ; -> Word: &0001204C
        LDR     R2,[R0,#0]
        LDREQ   R1,|FBOFFSETA|                  ; -> Word: &FFFFCFCD
        LDRNE   R1,|FBOFFSETB|                  ; -> Word: &FFFFCE8C
        STR     R2,|FRAMEBUFFER11RESTORECOPY|                  ; -> Word: &00000000
        ADD     R2,R2,R1
        STR     R2,[R0,#0]
        BL      |DRAWGAUGES|

        ; Restore the original address
        LDR     R0,|FRAMEBUFFER11|                  ; -> Word: &0001204C
        LDR     R1,|FRAMEBUFFER11RESTORECOPY|                  ; -> Word: &00000000
        STR     R1,[R0,#0]

        LDR     R14,|RETFROMPERIODICALLYDRAWGAUGES|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|SERVICENORMALAIRCRAFT|
        ; R0 = aircraft pointer
        ; R1 = AircraftCtrlX
        ; R2 = AircraftCtrlY
        STR     R0,|PPLAYERINFO5|                  ; -> Word: &00019AA4, Function entry, (alters flags)
        STR     R1,|PLANEANGLEX|                  ; -> Word: &00000000
        STR     R2,|PLANEANGLEY|                  ; -> Word: &00000000
        STR     R14,|RETFROMSERVICENORMALAIRCRAFT| ; -> Word: &00000000
        LDMIA   R0,{R1-R5} ; load aircraft attitude and R5=speed

        STR     R5,|AIRCRAFTSPEED|                  ; -> Word: &00000000

        ; Decode AircraftPitch into a Boolean value
        MOV     R14,#0
        CMP     R1,#QuarterTurn:SHL:AngleShift                      ; =&168000
        MOVGT   R14,#1

        LDR     R6,|THREEQUARTERTURN6|                  ; -> Word: &00438000
        CMP     R1,R6
        MOVGT   R14,#0
        STR     R14,|AIRCRAFTISUPSIDEDOWN|                 ; -> Word: &00000000

        ; Consume fuel at a rate proportionate to the throttle setting
        LDR     R6,[R0,#AircraftThrottle]                   ; =48
        LDR     R7,[R0,#AircraftFuel]                   ; =1<<6
        SUB     R7,R7,R6,ASR #ThrottleToFuelLog2
        CMP     R7,#0
        MOVLT   R7,#0
        STR     R7,[R0,#AircraftFuel]                   ; =1<<6

        SUB     R5,R5,R5,ASR #FrictionLog2
        ADDGT   R5,R5,R6,LSL #ThrottleToThrustLog2

        LDR     R12,[R0,#AircraftUnknown]                  ; =52

        LDR     R8,[R0,#AircraftDamage]                   ; =56
        CMP     R8,#(FatalAircraftDamage-1)                      ; =10
        MOVGT   R8,#0
        STRGT   R8,[R0,#AircraftThrottle]                   ; =48
        CMP     R5,#&29,22                      ; =&A400
        BGT     |TOOFAST|

        RSB     R10,R5,#&29,22                  ; =&A400
        LDR     R14,|AIRCRAFTISUPSIDEDOWN|                 ; -> Word: &00000000
        CMP     R14,#0
        ADDEQ   R12,R12,R10,ASR #7
        SUBNE   R12,R12,R10,ASR #7

|TOOFAST|
        CMP     R12,#&02,22                     ; =&800
        MOVGT   R12,#&02,22                     ; =&800
        CMN     R12,#&02,22                     ; =&800
        MVNLT   R12,#&02,22                     ; =&800
        SUB     R12,R12,R12,ASR #AircraftUnknownDecayLog2
        STR     R12,[R0,#AircraftUnknown]                  ; =52

        XABS    R12
        MOV     R12,R12,ASR #1 ; abs(AircraftUnknown)/2
        RSB     R12,R12,#AircraftUnknownMax/2     ; =&1000
        CMP     R12,#&C8                        ; ="" (200)
        MOVLT   R12,#&C8                        ; ="" (200)

        LDR     R6,|PLANEANGLEX|                  ; -> Word: &00000000
        MUL     R7,R6,R12
        MOV     R6,R7,ASR #12
        STR     R6,|PLANEANGLEX|                  ; -> Word: &00000000

        LDR     R6,|PLANEANGLEY|                  ; -> Word: &00000000
        MUL     R7,R6,R12
        MOV     R6,R7,ASR #12
        STR     R6,|PLANEANGLEY|                  ; -> Word: &00000000

        LDR     R12,[R0,#AircraftCoordZ] ; bug? unused

        CMP     R8,#(FatalAircraftDamage-1)                      ; =10
        MOVGT   R6,#&0A                         ; =10
        STRGT   R6,|PLANEANGLEX|                  ; -> Word: &00000000
        MOVGT   R6,#&14                         ; =20
        STRGT   R6,|PLANEANGLEY|                  ; -> Word: &00000000
        LDR     R8,[R0,#AircraftDamage]                   ; =56
        CMP     R8,#FatalAircraftDamage                         ; =11
        BNE     |NOTSMOKING|

        LDR     R12,|PTMPSTORE|                 ; -> Word: &0001898C
        STMIA   R12,{R0-R12}

        LDR     R2,[R0,#AircraftCoordZ]                   ; =28
        CMP     R2,#AircraftCentreZCoord               ; =&A000
        MOVEQ   R3,#CrashDamage                 ; =13
        STREQ   R3,[R0,#AircraftDamage]                   ; =56

        LDR     R6,[R0,#AircraftType]                   ; =140
        CMP     R6,#ATYPE_GOTHA_G_IV_BOMBER
        CMPNE   R6,#ATYPE_CARGO_AIRCRAFT
        LDR     R2,[R0,#AircraftCoordX]                   ; =20
        LDR     R3,[R0,#AircraftCoordY]                   ; =24
        LDR     R4,[R0,#AircraftCoordZ]                   ; =28
        MOV     R5,#SmokeTypeQuickBlack
        MOVEQ   R5,#SmokeTypeSlowBlack
        BL      |ADDSMOKEGEN|

        LDR     R12,|PTMPSTORE|                 ; -> Word: &0001898C
        LDMIA   R12,{R0-R12}
|NOTSMOKING|
        ; R3 = AircraftRoll
        MOV     R6,R3,ASR #AngleShift
        BIC     R6,R6,#AngleStepMask
        LDR     R7,|COSINE6|                  ; -> Word: MemCosine
        LDR     R8,|SINE6|                  ; -> Word: MemSine
        LDR     R11,[R7,R6] ; get cosine(AircraftRoll)
        LDR     R12,[R8,R6] ; get sine(AircraftRoll)

        ; R5 = speed
        CMP     R5,#&0A,22                      ; =&2800
        MOVLE   R6,#0
        LDRGT   R6,|PLANEANGLEX|                  ; -> Word: &00000000
        ADD     R3,R3,R6,LSL #10 ; Adjust AircraftRoll

        LDRGT   R6,|PLANEANGLEY|                  ; -> Word: &00000000
        ADD     R6,R6,R6,ASR #2

        MUL     R10,R6,R11
        ADD     R1,R1,R10,ASR #3 ; Adjust AircraftPitch

        MUL     R10,R6,R12

        LDR     R14,|AIRCRAFTISUPSIDEDOWN|                 ; -> Word: &00000000
        CMP     R14,#1
        BEQ     |L00009C5C|

        ADD     R2,R2,R10,ASR #3 ; Adjust AircraftHeading

        CMP     R12,#0
        ADDGT   R1,R1,R12,LSL #1 ; Adjust AircraftPitch
        SUBLE   R1,R1,R12,LSL #1

        SUB     R2,R2,R12,LSL #2 ; Adjust AircraftHeading
        B       |L00009C70|                     ; Ends

|L00009C5C|
        SUB     R2,R2,R10,ASR #3 ; Adjust AircraftHeading

        CMP     R12,#0
        SUBGT   R1,R1,R12,LSL #1 ; Adjust AircraftPitch
        ADDLE   R1,R1,R12,LSL #1

        ADD     R2,R2,R12,LSL #2 ; Adjust AircraftHeading

|L00009C70|
        LDR     R14,|TAKEOFFALTITUDE|                 ; -> Word array: &0000A000
        LDR     R10,[R0,#AircraftCoordZ]                  ; =28
        CMP     R10,R14
        MOVGT   R6,R4,ASR #AngleShift
        BICGT   R6,R6,#AngleStepMask
        LDRGT   R11,[R8,R6] ; get sine
        ADDGT   R5,R5,R11,ASR #1 ; adjust speed

        LDR     R8,[R0,#AircraftDamage]                   ; =56
        CMP     R8,#FatalAircraftDamage                         ; =11
        BLE     |AIRCRAFTNOTDEAD|

        ; An aircraft is dead
        ADD     R8,R8,#1
        CMP     R8,#MaxAircraftDamage                     ; ="#" (35)
        BGT     |REVIVEAIRCRAFTIFPRACTICE|

        STR     R8,[R0,#AircraftDamage]                   ; =56
        CMP     R8,#ExplodedAircraftDamage        ; =20
        MOV     R1,#HalfTurn:SHL:AngleShift                      ; =&2D0000
        MOV     R3,#0
        BGT     |PLAYERALREADYEXPLODED2|

        LDR     R12,|PTMPSTORE|                 ; -> Word: &0001898C
        STMIA   R12,{R0-R12}

        LDR     R1,|PPLAYERINFO6|                  ; -> Word: &00019AA4
        LDR     R2,[R0,#AircraftScoreIncrement]                   ; =164

        LDR     R3,[R1,#AircraftScore]                   ; =60
        ADD     R3,R3,R2
        STR     R3,[R1,#AircraftScore]                   ; =60

        CMP     R8,#FatalAircraftDamage ; bug?

        MOV     R8,#ExplodedAircraftDamage     ; =20
        STR     R8,[R0,#AircraftDamage]                   ; =56

        LDR     R8,[R0,#AircraftType]                   ; =140
        MOV     R5,#ExplosionStyleMedium

        CMP     R8,#ATYPE_GOTHA_G_IV_BOMBER
        MOVEQ   R5,#ExplosionStyleSmall                         ; ="c" (99)

        CMP     R8,#ATYPE_CARGO_AIRCRAFT
        MOVEQ   R5,#ExplosionStyleHuge                         ; ="b" (98)

        LDR     R2,[R0,#AircraftCoordX]                   ; =20
        LDR     R3,[R0,#AircraftCoordY]                   ; =24
        LDR     R4,[R0,#AircraftCoordZ]                   ; =28
        BL      |ADDEXPLOSION|

        LDR     R2,[R0,#AircraftType]                   ; =140
        LDR     R1,|HITLIST4|                  ; -> Word array: MemHitList
        LDRB    R3,[R1,R2]
        ADD     R3,R3,#1
        STRB    R3,[R1,R2]

        LDR     R12,|PTMPSTORE|                 ; -> Word: &0001898C
        LDMIA   R12,{R0-R12}
|PLAYERALREADYEXPLODED2|
        MOV     R12,#0
        STR     R12,[R0,#AircraftUnknown]                  ; =52

        MOV     R5,#CrashingAircraftSpeed               ; =11

|AIRCRAFTNOTDEAD|
        ; R5 = new speed
        LDR     R11,|AIRCRAFTSPEED|                 ; -> Word: &00000000
        ADD     R5,R5,R11
        MOV     R5,R5,ASR #1 ; mean of old and new speed

        LDR     R10,[R0,#AircraftUnknown]                  ; =52
        ADD     R1,R1,R10,LSL #6 ; Adjust AircraftPitch
        MOV     R4,R1 ; assign AircraftPitch to AircraftAngleW
        ADD     R4,R4,R10,LSL #9 ; Adjust AircraftAngleW

        CMP     R5,#&06,20                      ; =&6000
        BGT     |TOOFASTORAIRBORNE|

        LDR     R10,[R0,#AircraftCoordZ]                  ; =28
        LDR     R14,|TAKEOFFALTITUDE|                 ; -> Word array: &0000A000
        CMP     R10,R14
        BNE     |TOOFASTORAIRBORNE|

        ; Adjust AircraftAngleW when slow on the ground
        LDR     R14,|AIRCRAFTISUPSIDEDOWN|                 ; -> Word: &00000000
        CMP     R14,#0
        MOVEQ   R4,#UnknownAngle:SHL:AngleShift                ; =&8000
        MOVNE   R4,#HalfTurn:SHL:AngleShift     ; =&2D0000
        SUBNE   R4,R4,#UnknownAngle:SHL:AngleShift             ; =&8000

|TOOFASTORAIRBORNE|
        CMP     R1,#0 ; AircraftPitch
        ADDLT   R1,R1,#FullRotation:SHL:AngleShift                   ; =&5A0000
        CMP     R1,#FullRotation:SHL:AngleShift                      ; =&5A0000
        SUBGT   R1,R1,#FullRotation:SHL:AngleShift                   ; =&5A0000

        CMP     R2,#0 ; AircraftHeading
        ADDLT   R2,R2,#FullRotation:SHL:AngleShift                   ; =&5A0000
        CMP     R2,#FullRotation:SHL:AngleShift                      ; =&5A0000
        SUBGT   R2,R2,#FullRotation:SHL:AngleShift                   ; =&5A0000

        CMP     R3,#0 ; AircraftRoll
        ADDLT   R3,R3,#FullRotation:SHL:AngleShift                   ; =&5A0000
        CMP     R3,#FullRotation:SHL:AngleShift                      ; =&5A0000
        SUBGT   R3,R3,#FullRotation:SHL:AngleShift                   ; =&5A0000

        CMP     R4,#0 ; AircraftAngleW
        ADDLT   R4,R4,#FullRotation:SHL:AngleShift                   ; =&5A0000
        CMP     R4,#FullRotation:SHL:AngleShift                      ; =&5A0000
        SUBGT   R4,R4,#FullRotation:SHL:AngleShift                   ; =&5A0000

        STMIA   R0,{R1-R5} ; store aircraft attitude and speed
|FINISHEDAIRCRAFT|
        LDR     R14,|RETFROMSERVICENORMALAIRCRAFT| ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|SETVIEWIFDEAD|
        ; Is aircraft to view dead?
        LDR     R12,|P3PPLAYERINFO2|                 ; -> Word: &00012048, Function entry, (alters flags)
        LDR     R12,[R12,#0]
        LDR     R12,[R12,#PlayerAircraftToViewPtr]                 ; =272
        LDR     R11,[R12,#AircraftDamage]                 ; =56
        CMP     R11,#(FatalAircraftDamage-1)                     ; =10
        MOVLE   PC,R14                          ; Function exit if LE

        ; Is view already from the outside righthand quarter?
        LDR     R1,[R12,#AircraftViewIn]                  ; =44
        LDR     R2,[R12,#AircraftViewQuarter]                  ; =36
        CMP     R1,#ViewOutside
        CMPEQ   R2,#QuarterRight
        MOVEQ   PC,R14                          ; Function exit if EQ

        LDR     R1,|P4PREVENTTIMESKIP|                  ; -> Word: &00015714
        STR     PC,[R1,#0]

        MOV     R1,#ViewOutside
        STR     R1,[R12,#AircraftViewIn]                  ; =44

        MOV     R1,#QuarterTurn                      ; =&5A0
        STR     R1,[R12,#AircraftViewAngle]                  ; =40

        MOV     R1,#QuarterRight
        STR     R1,[R12,#AircraftViewQuarter]                  ; =36

        MOV     PC,R14                          ; Function exit, Ends

|P3PPLAYERINFO2|
        DCD     |PPLAYERINFO2|
|THUNDERCOUNTDOWN10|
        DCD     &00000000                       ; Word r/w (referenced)
|PMISSIONNUM4|
        DCD     |MISSIONNUM|
|P2FRAMECOUNTDOWN1024|
        DCD     |FRAMECOUNTDOWN1024|

|THUNDER|
        LDR     R0,|PMISSIONNUM4|                  ; -> Word: &000177B8, Function entry, (alters flags)
        LDR     R0,[R0,#0]
        CMP     R0,#&0F                         ; =15
        CMPNE   R0,#&10                         ; =16
        CMPNE   R0,#&1C                         ; =28
        MOVNE   PC,R14                          ; Function exit if NE

        LDR     R0,|THUNDERCOUNTDOWN10|                  ; -> Word: &00000000
        SUBS    R0,R0,#1
        MOVMI   R0,#0
        STR     R0,|THUNDERCOUNTDOWN10|                  ; -> Word: &00000000

        ; Thunder three times every 1025 frames
        LDR     R0,|P2FRAMECOUNTDOWN1024|                  ; -> Word: &000113F4
        LDR     R0,[R0,#0]
        CMP     R0,#1
        CMPNE   R0,#&19,28                      ; =&190
        CMPNE   R0,#&0A,26                      ; =&280
        MOVNE   PC,R14                          ; Function exit if NE

        MOV     R0,#ThunderCountdownReinit                         ; =10
        STR     R0,|THUNDERCOUNTDOWN10|                  ; -> Word: &00000000

        MOV     R0,#ChannelMisc
        MOV     R1,#VoiceExplode
        SWI     Sound_AttachVoice

        MOV     R0,#ChannelMisc
        MVN     R1,#MaxVolume
        MOV     R2,#ThunderPitch      ; =&5A0
        MOV     R3,#&0A                         ; =10
        SWI     Sound_Control

        MOV     PC,R14                          ; Function exit, Ends

|PPLAYER1COORDS2|
        DCD     |PLAYER1COORDS|
|PPLAYER2COORDS2|
        DCD     |PLAYER2COORDS|
|RETFROMSERVICEFLAKGUN|
        DCD     &00000000                       ; Word r/w (referenced)
|PCOUNT0TO2|
        DCD     |COUNT0TO2|
|PPREVENTTIMEWARP2|
        DCD     |PREVENTTIMEWARP|
|FLAKTARGETAIRCRAFTCOORDS|
        DCD     &00000000                       ; Word r/w (referenced)

|SERVICEFLAKGUN|
        ; R0-R2 = pos of flak gun
        LDR     R3,|PPLAYER1COORDS2|                  ; -> Word: &00019AB8, Function entry, (alters flags)
        LDR     R7,|PPLAYER2COORDS2|                  ; -> Word: &00019CC4
        LDR     R4,[R3,#(AircraftDamage-AircraftCoord)]                   ; =36
        CMP     R4,#FatalAircraftDamage                         ; =11
        MOVGE   R3,R7 ; player 1 is dead so target player 2
        BGE     |FLAKTARGETCHOSEN|

        LDR     R4,[R7,#(AircraftDamage-AircraftCoord)]                   ; =36
        CMP     R4,#FatalAircraftDamage                         ; =11
        BGE     |FLAKTARGETCHOSEN| ; player 2 is dead so target player 1

        LDMIA   R3,{R4-R6} ; get player 1 pos
        LDMIA   R7,{R8-R10} ; get player 2 pos

        XABSDIFF R4,R4,R0 ; calc player 1 dist from flak gun
        XABSDIFF R5,R5,R1
        XABSDIFF R6,R6,R2

        CMP     R4,R5 ; R4 = max player 1 dist from flak gun
        MOVLT   R4,R5
        CMP     R6,R4
        MOVGT   R4,R6

        XABSDIFF R8,R8,R0 ; calc player 2 dist from flak gun
        XABSDIFF R9,R9,R1
        XABSDIFF R10,R10,R2

        CMP     R8,R9
        MOVLT   R8,R9
        CMP     R10,R8
        MOVGT   R8,R10 ; R8 = max player 2 dist from flak gun

        CMP     R8,R4 ; is player 2 nearer?
        MOVLT   R3,R7 ; yes, target player 2

|FLAKTARGETCHOSEN|
        ; R0-R2 = pos of flak gun
        ; R3 = aircraft to target
        STR     R3,|FLAKTARGETAIRCRAFTCOORDS|                  ; -> Word: &00000000
        LDMIA   R3,{R3-R5} ; get target aircraft pos

        ABSDIFF R6,R0,R3 ; calc target aircraft dist from flak gun
        ABSDIFF R7,R1,R4
        ABSDIFF R8,R2,R5

        CMP     R6,#FlakGunRange                      ; =&1400000
        MOVGT   PC,R14                          ; Function exit if GT

        CMP     R7,#FlakGunRange                      ; =&1400000
        MOVGT   PC,R14                          ; Function exit if GT

        CMP     R8,#FlakGunRange                      ; =&1400000
        MOVGT   PC,R14                          ; Function exit if GT

        LDR     R10,|PPREVENTTIMEWARP2|                 ; -> Word: &00015188
        STR     PC,[R10,#0] ; Don't allow timewarp during flak

        LDR     R10,|FLAKTARGETAIRCRAFTCOORDS|                 ; -> Word: &00000000
        LDR     R10,[R10,#(AircraftDamage-AircraftCoord)]                 ; =36
        CMP     R10,#FatalAircraftDamage                        ; =11
        MOVGE   PC,R14 ; target is already dead

        EOR     R10,R0,R1 ; x,y coords of flak gun
        LDR     R11,|PCOUNT0TO2|                 ; -> Word: &00011FB8
        LDR     R11,[R11,#0]
        EOR     R10,R11,R10
        TST     R10,#3
        MOVNE   PC,R14 ; not ready to fire this time

        STR     R14,|RETFROMSERVICEFLAKGUN|                 ; -> Word: &00000000

        ; R6-R8 = x,y,z distance to target
        MOV     R6,R6,ASR #20
        MOV     R7,R7,ASR #20
        MOV     R8,R8,ASR #20

        MOV     R11,R6
        MUL     R10,R6,R11 ; x squared

        MOV     R11,R7
        MUL     R12,R7,R11 ; y squared

        ADD     R12,R12,R10 ; x squared + y squared

        MOV     R11,R8
        MUL     R10,R8,R11 ; z squared

        ADD     R6,R10,R12 ; x squared + y squared + z squared

        CMP     R6,#&01,24                      ; =&100
        MOVGT   R12,#&48                        ; ="H" (72)
        BGT     |CHOSENFLAKTARGETRANGE|

        CMP     R6,#&79                         ; ="y" (121)
        BGT     |LONGRANGEFLAK|

        CMP     R6,#&24                         ; ="$" (36)
        BGT     |MEDIUMRANGEFLAK|

        ; Close range
        CMP     R6,#0
        MOVEQ   R12,#0
        BEQ     |CHOSENFLAKTARGETRANGE|

        CMP     R6,#1
        MOVEQ   R12,#4
        BEQ     |CHOSENFLAKTARGETRANGE|

        CMP     R6,#4
        MOVLT   R12,#8
        BLT     |CHOSENFLAKTARGETRANGE|

        CMP     R6,#9
        MOVLT   R12,#&0C                        ; =12
        BLT     |CHOSENFLAKTARGETRANGE|

        CMP     R6,#&10                         ; =16
        MOVLT   R12,#&10                        ; =16
        BLT     |CHOSENFLAKTARGETRANGE|

        MOV     R12,#&14                        ; =20
        B       |CHOSENFLAKTARGETRANGE|                     ; Ends

|MEDIUMRANGEFLAK|
        CMP     R6,#&24                         ; ="$" (36)
        MOVLT   R12,#&18                        ; =24
        BLT     |CHOSENFLAKTARGETRANGE|

        CMP     R6,#&31                         ; ="1" (49)
        MOVLT   R12,#&1C                        ; =28
        BLT     |CHOSENFLAKTARGETRANGE|

        CMP     R6,#&40                         ; ="@" (64)
        MOVLT   R12,#&20                        ; =" " (32)
        BLT     |CHOSENFLAKTARGETRANGE|

        CMP     R6,#&51                         ; ="Q" (81)
        MOVLT   R12,#&24                        ; ="$" (36)
        BLT     |CHOSENFLAKTARGETRANGE|

        MOV     R12,#&28                        ; ="(" (40)
        B       |CHOSENFLAKTARGETRANGE|                     ; Ends

|LONGRANGEFLAK|
        CMP     R6,#&79                         ; ="y" (121)
        MOVLT   R12,#&2C                        ; ="," (44)
        BLT     |CHOSENFLAKTARGETRANGE|

        CMP     R6,#&94                         ; ="" (148)
        MOVLT   R12,#&30                        ; ="0" (48)
        BLT     |CHOSENFLAKTARGETRANGE|

        CMP     R6,#&A9                         ; ="" (169)
        MOVLT   R12,#&34                        ; ="4" (52)
        BLT     |CHOSENFLAKTARGETRANGE|

        CMP     R6,#&C4                         ; ="" (196)
        MOVLT   R12,#&38                        ; ="8" (56)
        BLT     |CHOSENFLAKTARGETRANGE|

        MOV     R12,#&3C                        ; ="<" (60)

|CHOSENFLAKTARGETRANGE|
        ; R0-R2 = pos of flak gun
        ; R3-R5 = pos of target aircraft
        ; R12 = deflection factor
        ADD     R12,R12,#3

        LDR     R6,|FLAKTARGETAIRCRAFTCOORDS|                  ; -> Word: &00000000
        ADD     R6,R6,#(AircraftCoordCopy-AircraftCoord)      ; ="" (136)
        LDMIA   R6,{R6-R8} ; get previous pos of target aircraft?

        SUB     R6,R6,R3 ; vector is previous - current pos?
        SUB     R7,R7,R4
        SUB     R8,R8,R5

        MUL     R6,R12,R6 ; apply deflection shooting factor?
        MUL     R7,R12,R7
        MUL     R8,R12,R8

        SUB     R3,R3,R6 ; predict new position of target
        SUB     R4,R4,R7
        SUB     R5,R5,R8

        STMFD   R13!,{R0-R5}
        SUB     R11,R3,R0 ; predicted target x - gun x
        SUB     R12,R1,R4 ; gun y - predicted target y
        BL      |FINDANGLE| ; R11,R12 = length of sides, returns angle in R1

        MOV     R11,R1
        LDMFD   R13,{R0-R5}
        BIC     R11,R11,#AngleStepMask
        STMFD   R13!,{R11}

        LDR     R6,|COSINE8|                  ; -> Word: MemCosine
        LDR     R7,|SINE8|                  ; -> Word: MemSine
        LDR     R6,[R6,R11]
        LDR     R7,[R7,R11]

        SUB     R11,R3,R0
        SUB     R12,R4,R1

        MOV     R11,R11,ASR #AngleShift
        MOV     R12,R12,ASR #AngleShift

        MUL     R9,R11,R7
        MUL     R10,R12,R6

        ABS     R9
        ABS     R10

        ADD     R12,R9,R10
        MOV     R12,R12,ASR #2
        SUB     R11,R2,R5 ; gun z - predicted target z
        BL      |FINDANGLE| ; R11,R12 = length of sides, returns angle in R1

        MOV     R11,R1
        LDMFD   R13!,{R3-R9}
        EOR     R0,R7,R8 ; predicted target x,y
        EOR     R1,R8,R9 ; predicted target y,z
        BIC     R7,R11,#AngleStepMask
        MOV     R8,R3
        TST     R0,#1
        ADDNE   R7,R7,#&0C                      ; =12
        TST     R0,#2
        SUBNE   R7,R7,#&0C                      ; =12
        TST     R1,#1
        ADDNE   R8,R8,#&0C                      ; =12
        TST     R1,#2
        SUBNE   R8,R8,#&0C                      ; =12
        TST     R0,#4
        ADDNE   R7,R7,#&0C                      ; =12
        TST     R0,#8
        SUBNE   R7,R7,#&0C                      ; =12
        TST     R1,#4
        ADDNE   R8,R8,#&0C                      ; =12
        TST     R1,#8
        SUBNE   R8,R8,#&0C                      ; =12
        MOV     R9,#FlakAimHeight               ; ="c" (99)
        BL      |ADDFLAK|

        LDR     R14,|RETFROMSERVICEFLAKGUN|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|COSINE7|
        DCD     MemCosine                       ; Word r/- (referenced)
|SINE7|
        DCD     MemSine                       ; Word r/- (referenced)

|COPYFRAMEBUFFERADDR|
        STR     R2,|FRAMEBUFFER12|                  ; -> Word: &00000000, Function entry, (alters flags)
        MOV     PC,R14                          ; Function exit, Ends

|PPLAYER1INFO19|
        DCD     |PLAYER1INFO|
|PSPLITSCREEN11|
        DCD     |SPLITSCREEN|

|MAYBEDRAWFRONTCOCKPIT|
        LDR     R1,|PPLAYER1INFO19|                  ; -> Word: &00019AA4, Function entry, (alters flags)
        LDR     R1,[R1,#AircraftViewMap]                   ; =168
        CMP     R1,#0
        MOVNE   PC,R14                          ; Function exit if NE

        LDR     R1,|PSPLITSCREEN11|                  ; -> Word: &00016B28
        LDR     R1,[R1,#0]
        CMP     R1,#0
        MOVNE   PC,R14                          ; Function exit if NE

        ; Draw bottom wing by copying a non-masked bitmap
        LDR     R0,|FRAMEBUFFER12|                  ; -> Word: &00000000
        LDR     R1,|FRONTBOTTOMWINGOFFSETINFRAME|   ; -> Word: &00012E80
        ADD     R0,R0,R1
        MOV     R1,#((FrontBottomWingHeight*RowStride)/PixelCopyChunk)-1    ; ="o" (111)
        LDR     R2,|GRAPHICS|                  ; -> Word: &00057380
|DRAWBOTTOMLOOP|
        LDMIA   R2!,{R3-R12} ; copy PixelCopyChunk pixels at a time
        STMIA   R0!,{R3-R12}
        SUBS    R1,R1,#1
        BPL     |DRAWBOTTOMLOOP|

        MOV     R0,#ViewFront

|DRAWCOCKPIT|
        ; R0 = view direction
        LDR     R1,|PPLAYER1INFO19|                  ; -> Word: &00019AA4, Function entry
        LDR     R1,[R1,#AircraftViewMap]                   ; =168
        CMP     R1,#0
        MOVNE   PC,R14                          ; Function exit if NE

        LDR     R1,|PSPLITSCREEN11|                  ; -> Word: &00016B28
        LDR     R1,[R1,#0]
        CMP     R1,#0
        MOVNE   PC,R14                          ; Function exit if NE

        STR     R14,|RETFROMDRAWCOCKPIT|                 ; -> Word: &00000000
        CMP     R0,#ViewRear
        BEQ     |DRAWREARVIEW|
        BGT     |DRAWRIGHTVIEW|

        CMP     R0,#ViewLeft
        BEQ     |DRAWLEFTVIEW|

        ; Draw front view

        ; Copy non-masked bitmap
        LDR     R0,|FRAMEBUFFER12|                  ; -> Word: &00000000
        LDR     R1,|FRONTBOTTOMWINGOFFSETINFRAME|                  ; -> Word: &00012E80
        ADD     R0,R0,R1
        MOV     R1,#((FrontBottomWingPerFrameHeight*RowStride)/PixelCopyChunk)-1         ; =15
        LDR     R2,|GRAPHICS|                  ; -> Word: &00057380
|DRAWUNMASKEDPIXELCHUNKLOOP|
        LDMIA   R2!,{R3-R12} ; copy PixelCopyChunk pixels at a time
        STMIA   R0!,{R3-R12}
        SUBS    R1,R1,#1
        BPL     |DRAWUNMASKEDPIXELCHUNKLOOP|

        LDR     R2,|FRONTTOPMASKEDBITMAP|           ; -> Word: &00058500
        LDR     R0,|FRAMEBUFFER12|                  ; -> Word: &00000000

        MOV     R1,#(FrontTopWingHeight*RowStride)/PixelCopyChunk  ; ="@" (64)
        STR     R1,|DRAWMASKEDCOUNT|                  ; -> Word: &00000000

        BL      |DRAWMASKED| ; Draw top wing

        LDR     R2,|FRONTCOCKPITMASKEDBITMAP|       ; -> Word: &00058F00

        LDR     R0,|FRAMEBUFFER12|                  ; -> Word: &00000000
        LDR     R1,|FRONTCOCKPITOFFSETINFRAME|                  ; -> Word: &00010CC0
        ADD     R0,R0,R1

        MOV     R1,#(FrontCockpitHeight*RowStride)/PixelCopyChunk ; ="" (224)
        STR     R1,|DRAWMASKEDCOUNT|                  ; -> Word: &00000000

        BL      |DRAWMASKED| ; Draw cockpit

        LDR     R0,|FRAMEBUFFER12|                  ; -> Word: &00000000
        LDR     R1,|FRONTNOSEOFFSETINFRAME|                  ; -> Word: &0000C850
        ADD     R0,R0,R1

        MOV     R1,#FrontNoseHeight              ; ="7" (55)
        STR     R1,|DRAWMASKEDCOUNT|                  ; -> Word: &00000000

        MOV     R1,#NoseWidth/PixelCopyChunk
        STR     R1,|DRAWMASKEDCOUNT2|                  ; -> Word: &00000000

        BL      |DRAWMASKEDNOSE| ; Draw nose

        LDR     R14,|RETFROMDRAWCOCKPIT|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|DRAWMASKED|
        ; R0 = frame buffer address
        ; R2 = masked bitmap
        STR     R14,|RETFROMDRAWMASKED|                 ; -> Word: &00000000, Function entry, (alters flags)
        LDR     R14,|MASKCOLOUR|                 ; -> Word: &83838383
|DRAWMASKEDPIXELCHUNKLOOP|
        LDMIA   R2!,{R3-R12}

        DRAWMASKEDQUAD R3,R0,R14,R1
        DRAWMASKEDQUAD R4,R0,R14,R1
        DRAWMASKEDQUAD R5,R0,R14,R1
        DRAWMASKEDQUAD R6,R0,R14,R1
        DRAWMASKEDQUAD R7,R0,R14,R1
        DRAWMASKEDQUAD R8,R0,R14,R1
        DRAWMASKEDQUAD R9,R0,R14,R1
        DRAWMASKEDQUAD R10,R0,R14,R1
        DRAWMASKEDQUAD R11,R0,R14,R1
        DRAWMASKEDQUAD R12,R0,R14,R1

        LDR     R1,|DRAWMASKEDCOUNT|                  ; -> Word: &00000000
        SUB     R1,R1,#1
        STR     R1,|DRAWMASKEDCOUNT|                  ; -> Word: &00000000

        CMP     R1,#0
        BGT     |DRAWMASKEDPIXELCHUNKLOOP|

        LDR     R14,|RETFROMDRAWMASKED|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|DRAWMASKEDNOSE|
        ; R0 = frame buffer address
        ; R2 = masked bitmap
        STR     R14,|RETFROMDRAWMASKED|                 ; -> Word: &00000000, Function entry, (alters flags)
        LDR     R14,|MASKCOLOUR|                 ; -> Word: &83838383
|DRAWMASKEDNOSEPIXELCHUNKLOOP|
        LDMIA   R2!,{R3-R12}

        DRAWMASKEDQUAD R3,R0,R14,R1
        DRAWMASKEDQUAD R4,R0,R14,R1
        DRAWMASKEDQUAD R5,R0,R14,R1
        DRAWMASKEDQUAD R6,R0,R14,R1
        DRAWMASKEDQUAD R7,R0,R14,R1
        DRAWMASKEDQUAD R8,R0,R14,R1
        DRAWMASKEDQUAD R9,R0,R14,R1
        DRAWMASKEDQUAD R10,R0,R14,R1
        DRAWMASKEDQUAD R11,R0,R14,R1
        DRAWMASKEDQUAD R12,R0,R14,R1

        LDR     R1,|DRAWMASKEDCOUNT2|                  ; -> Word: &00000000
        SUB     R1,R1,#1
        STR     R1,|DRAWMASKEDCOUNT2|                  ; -> Word: &00000000

        CMP     R1,#0
        BGT     |DRAWMASKEDNOSEPIXELCHUNKLOOP|

        ADD     R0,R0,#RowStride-NoseWidth                 ; ="" (160)

        MOV     R1,#NoseWidth/PixelCopyChunk
        STR     R1,|DRAWMASKEDCOUNT2|                  ; -> Word: &00000000

        LDR     R1,|DRAWMASKEDCOUNT|                  ; -> Word: &00000000
        SUB     R1,R1,#1
        STR     R1,|DRAWMASKEDCOUNT|                  ; -> Word: &00000000

        CMP     R1,#0
        BGT     |DRAWMASKEDNOSEPIXELCHUNKLOOP|

        LDR     R14,|RETFROMDRAWMASKED|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|DRAWREARVIEW|
        LDR     R0,|FRAMEBUFFER12|                  ; -> Word: &00000000
        LDR     R1,|REAROFFSETINFRAME|                  ; -> Word: &0000B900
        ADD     R0,R0,R1
        MOV     R1,#(RearHeight * RowStride) / PixelCopyChunk  ; =&360
        STR     R1,|DRAWMASKEDCOUNT|                  ; -> Word: &00000000
        LDR     R2,|REARMASKEDBITMAP|                  ; -> Word: &0005D460
        BL      |DRAWMASKED|

        LDR     R14,|RETFROMDRAWCOCKPIT|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|DRAWLEFTVIEW|
        LDR     R0,|FRAMEBUFFER12|                  ; -> Word: &00000000
        MOV     R1,#(SideTopWingHeight * RowStride) / PixelCopyChunk ; =&198
        STR     R1,|DRAWMASKEDCOUNT|                  ; -> Word: &00000000
        LDR     R2,|LEFTMASKEDBITMAP|                  ; -> Word: &00065B60
        BL      |DRAWMASKED|

        LDR     R0,|FRAMEBUFFER12|                  ; -> Word: &00000000
        LDR     R1,|LEFTOFFSETINFRAME|                  ; -> Word: &00010180
        ADD     R0,R0,R1
        MOV     R1,#&19,28                      ; =&190
        STR     R1,|DRAWMASKEDCOUNT|                  ; -> Word: &00000000
        BL      |DRAWMASKED|

        LDR     R14,|RETFROMDRAWCOCKPIT|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|DRAWRIGHTVIEW|
        LDR     R0,|FRAMEBUFFER12|                  ; -> Word: &00000000
        MOV     R1,#(SideTopWingHeight * RowStride) / PixelCopyChunk  ; =&198
        STR     R1,|DRAWMASKEDCOUNT|                  ; -> Word: &00000000
        LDR     R2,|RIGHTMASKEDBITMAP|                  ; -> Word: &0006D9A0
        BL      |DRAWMASKED|

        LDR     R0,|FRAMEBUFFER12|                  ; -> Word: &00000000
        LDR     R1,|RIGHTOFFSETINFRAME|                  ; -> Word: &00010180
        ADD     R0,R0,R1
        MOV     R1,#&19,28                      ; =&190
        STR     R1,|DRAWMASKEDCOUNT|                  ; -> Word: &00000000
        BL      |DRAWMASKED|

        LDR     R14,|RETFROMDRAWCOCKPIT|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|FRAMEBUFFER12|
        DCD     &00000000                       ; Word r/w (referenced)
|FRONTBOTTOMWINGOFFSETINFRAME|
        DCD     HeightExclFrontBottomWing*RowStride                ; Word r/- (referenced)
|FRONTCOCKPITOFFSETINFRAME|
        DCD     (HeightExclFrontBottomWing-FrontCockpitHeight+1)*RowStride ; Word r/- (referenced)
|FRONTNOSEOFFSETINFRAME|
        DCD     ((HeightExclFrontBottomWing-FrontCockpitHeight-FrontNoseHeight+1)*RowStride)+(WIDTH/2)-(NoseWidth/2) ; Word r/- (referenced)
|GRAPHICS|
        DCD     MemGraphics                     ; Word r/- (referenced)
|FRONTCOCKPITMASKEDBITMAP|
        DCD     MemGraphics + ((FrontBottomWingHeight+FrontTopWingHeight)*RowStride) ; Word r/- (referenced)
        DCD     &00000000                       ;~ Word -/-
|FRONTTOPMASKEDBITMAP|
        DCD     MemGraphics + (FrontBottomWingHeight*RowStride) ; Word r/- (referenced)
|RETFROMDRAWMASKED|
        DCD     &00000000                       ; Word r/w (referenced)
|RETFROMDRAWCOCKPIT|
        DCD     &00000000                       ; Word r/w (referenced)
|MASKCOLOUR|
        DCB     MaskByte,MaskByte,MaskByte,MaskByte   ; Word r/- (referenced)
|DRAWMASKEDCOUNT|
        DCD     &00000000                       ; Word r/w (referenced)
|DRAWMASKEDCOUNT2|
        DCD     &00000000                       ; Word r/w (referenced)
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
|REAROFFSETINFRAME|
        DCD     RearYOffset*RowStride                   ; Word r/- (referenced)
|REARMASKEDBITMAP|
        DCD     MemGraphics + ((FrontBottomWingHeight+FrontTopWingHeight+FrontCockpitHeight)*RowStride) + (FrontNoseHeight * NoseWidth)             ; Word r/- (referenced)
|LEFTOFFSETINFRAME|
        DCD     SideBottomWingYOffset*RowStride     ; Word r/- (referenced)
|LEFTMASKEDBITMAP|
        DCD     MemGraphics + ((FrontBottomWingHeight+FrontTopWingHeight+FrontCockpitHeight)*RowStride) + (FrontNoseHeight * NoseWidth) + (RearHeight*RowStride) ; Word r/- (referenced)
|RIGHTOFFSETINFRAME|
        DCD     SideBottomWingYOffset*RowStride           ; Word r/- (referenced)
|RIGHTMASKEDBITMAP|
        DCD     MemGraphics + ((FrontBottomWingHeight+FrontTopWingHeight+FrontCockpitHeight)*RowStride) + (FrontNoseHeight * NoseWidth) + (RearHeight*RowStride) + ((SideBottomWingHeight+SideTopWingHeight)*RowStride)   ; Word r/- (referenced)

|UPDATEAIRCRAFTCOORDS|
        ; r0 = aircraft pointer
        LDMIA   R0,{R1-R4} ; get x,y,z angles
        MOV     R2,R2,ASR #AngleShift
        MOV     R4,R4,ASR #AngleShift
        BIC     R2,R2,#AngleStepMask
        BIC     R4,R4,#AngleStepMask
        LDR     R5,|COSINE7|                  ; -> Word: MemCosine
        LDR     R6,|SINE7|                  ; -> Word: MemSine
        LDR     R8,[R5,R2] ; cosine(xr)
        LDR     R9,[R6,R2] ; sine(xr)
        LDR     R10,[R5,R4] ; cosine(zr)
        LDR     R11,[R6,R4] ; sine(zr)
        MUL     R12,R8,R10 ; cosine(xr) * cosine(zr)
        MOV     R8,R12,ASR #2
        MUL     R12,R9,R10 ; sine(xr) * cosine(zr)
        MOV     R9,R12,ASR #2

        LDR     R4,[R0,#AircraftSpeed]                   ; =16
        MOV     R4,R4,ASR #10

        ADD     R0,R0,#AircraftCoord                      ; =20
        LDMIA   R0,{R1-R3} ; load x,y,z coords

        MUL     R10,R9,R4
        ADD     R1,R1,R10,ASR #12 ; x += sine(xr) * cosine(zr) * speed
        MUL     R10,R8,R4
        SUB     R2,R2,R10,ASR #12 ; y -= cosine(xr) * cosine(zr) * speed
        MUL     R10,R11,R4
        SUB     R3,R3,R10,ASR #2 ; z -= sine(zr) * speed
        CMP     R3,#AircraftCentreZCoord               ; =&A000
        MOVLT   R3,#AircraftCentreZCoord               ; =&A000
        STMIA   R0,{R1-R3} ; store new x,y,z coords
        BLT     |SETCRASHDAMAGE|

        MOV     PC,R14                          ; Function exit, Ends

|COSINE8|
        DCD     MemCosine                       ; Word r/- (referenced)
|SINE8|
        DCD     MemSine                       ; Word r/- (referenced)

|SETCRASHDAMAGE|
        ; bug?
        LDR     R3,[R0,#(AircraftDamage-AircraftCoord)] ; =36
        CMP     R3,#FatalAircraftDamage                 ; =11
        MOVEQ   R3,#CrashDamage2                         ; =15
        STREQ   R3,[R0,#(AircraftDamage-AircraftCoord)] ; =36

        MOV     R3,#CrashDamage2                         ; =15
        STR     R3,[R0,#(AircraftDamage-AircraftCoord)] ; =36

        MOV     PC,R14                          ; Function exit, Ends

|OCEANFILLSRC|
        MAKEFILL RoyalAzure

|DESERTFILLSRC|
        MAKEFILL Honey

|SNOWFILLSRC|
        MAKEFILL OffWhite

|NIGHTLANDFILLSRC|
        MAKEFILL DarkGreen

|DAYLANDFILLSRC|
        MAKEFILL Olive

|PICMAPAIRCRAFTPRESETS|
        DCB     0,32,3,0                        ;~~
        DCD     &00258000                       ;~~~ Word -/-
        DCD     &00019000
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &0000A000                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000028                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &000222E0                       ;~~ Word -/-
|PLAYER1CAMERAPLANE|
        DCD     &00000000                       ;~ Word -/-
        DCD     (3*QuarterTurn):SHL:AngleShift                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00064000                       ;~~~ Word -/-
        DCD     &00000001                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000001                       ;~~~ Word -/-
        DCD     &00000001                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &000222E0                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     (3*QuarterTurn):SHL:AngleShift                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00064000                       ;~~~ Word -/-
        DCD     &00000001                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000001                       ;~~~ Word -/-
        DCD     &00000001                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &000222E0                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     ATYPE_CAMERA
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &249F0000                       ;~~~ Word -/-
        DCD     &249F0000                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000078                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     |PLAYER1INFO|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
|PLAYER2CAMERAPLANE|
        DCD     &00000000                       ;~ Word -/-
        DCD     (3*QuarterTurn):SHL:AngleShift                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00064000                       ;~~~ Word -/-
        DCD     &00000001                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000001                       ;~~~ Word -/-
        DCD     &00000001                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &000222E0                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     (3*QuarterTurn):SHL:AngleShift                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00064000                       ;~~~ Word -/-
        DCD     &00000001                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000001                       ;~~~ Word -/-
        DCD     &00000001                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &000222E0                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     ATYPE_CAMERA
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &249F0000                       ;~~~ Word -/-
        DCD     &249F0000                       ;~~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000078                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     |PLAYER2INFO|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
|RETFROMSERIAL|
        DCD     &00000000                       ; Word r/w (referenced)
        DCD     &00000000                       ;~ Word -/-
|SERIALISMASTER|
        DCD     &00000000                       ; Word r/- (referenced)

|DOSERIALLINK|
        STR     R14,|RETFROMSERIAL|                 ; -> Word: &00000000, Function entry, (alters flags)

        LDR     R10,|PPLAYER1INFO20|                 ; -> Word: &00019AA4
        LDR     R10,[R10,#AircraftSerialBitMask]                 ; =152
        TST     R10,#AircraftSerialBitExit
        MOVEQ   R10,#0
        MOVNE   R10,#1
        STR     R10,|EXITFLAG|                 ; -> Word: &00000000

        MOV     R10,R0
        MOV     R11,R1
        LDR     R0,|SERIALISMASTER|                  ; -> Word: &00000000
        CMP     R0,#0
        BEQ     |ISSLAVE|

        BL      |WriteBytesToSerial|
        BL      |ReadBytesFromSerial|
        B       |DONEMASTER|                     ; Ends

|ISSLAVE|
        BL      |ReadBytesFromSerial|
        BL      |WriteBytesToSerial|

|DONEMASTER|
        SUB     R4,R4,#AircraftSerialCentre                      ; ="x" (120)
        SUB     R5,R5,#AircraftSerialCentre                      ; ="x" (120)
        STR     R4,[R10,#AircraftCtrlX]                  ; =144
        STR     R5,[R10,#AircraftCtrlY]                  ; =148
        STR     R6,[R10,#AircraftSerialBitMask]                  ; =152
        TST     R6,#AircraftSerialBitFire
        BEQ     |L0000AD98|

        MOV     R0,#1
        STR     R0,[R10,#AircraftFireGun]                  ; =32
|L0000AD98|
        TST     R6,#AircraftSerialBitCloseThrot
        BEQ     |NOSERIALCLOSETHROT|

        LDR     R0,[R10,#AircraftThrottle]                  ; =48
        SUB     R0,R0,#ThrottleStep                     ; =10
        CMP     R0,#0
        MOVLT   R0,#0
        STR     R0,[R10,#AircraftThrottle]                  ; =48
|NOSERIALCLOSETHROT|
        TST     R6,#AircraftSerialBitOpenThrot
        BEQ     |NOSERIALOPENTHROT|

        LDR     R0,[R10,#AircraftThrottle]                  ; =48
        ADD     R0,R0,#ThrottleStep                     ; =10
        CMP     R0,#MaxThrottle                         ; ="d" (100)
        MOVGT   R0,#MaxThrottle                         ; ="d" (100)
        STR     R0,[R10,#AircraftThrottle]                  ; =48
|NOSERIALOPENTHROT|
        TST     R6,#AircraftSerialBitCrash              ; =" " (32)
        BEQ     |NOSERIALCRASH|

        MOV     R11,#CrashDamage                ; =13
        LDR     R0,|PPLAYER2INFO17|                  ; -> Word: &00019CB0
        LDR     R10,[R0,#AircraftDamage]                  ; =56
        CMP     R10,#FatalAircraftDamage                        ; =11
        STRLT   R11,[R0,#AircraftDamage]                  ; =56

        LDR     R11,|P4OUTPUT|                 ; -> Word: &00017A54
        MOV     R10,#OutputCollision
        STR     R10,[R11,#0]

|NOSERIALCRASH|
        LDR     R0,|PPLAYER1INFO20|                  ; -> Word: &00019AA4
        MOV     R1,#0
        STR     R1,[R0,#AircraftSerialBitMask]                   ; =152

        LDR     R10,|EXITFLAG|                 ; -> Word: &00000000
        CMP     R10,#1
        BEQ     |SERIALQUIT|

        TST     R6,#AircraftSerialBitExit
        BEQ     |NOSERIALQUIT|

|SERIALQUIT|
        MOV     R1,#AircraftSerialBitExit
        STR     R1,[R0,#AircraftSerialBitMask]                   ; =152

|NOSERIALQUIT|
        TST     R6,#AircraftSerialBitTimewarp                         ; ="@" (64)
        BEQ     |NOSERIALTIMEWARP|

        LDR     R1,[R0,#AircraftSerialBitMask]                   ; =152
        ADD     R1,R1,#AircraftSerialBitTimewarp                      ; ="@" (64)
        STR     R1,[R0,#AircraftSerialBitMask]                   ; =152

|NOSERIALTIMEWARP|
        LDR     R14,|RETFROMSERIAL|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|PPLAYER2INFO17|
        DCD     |PLAYER2INFO|
|P4OUTPUT|
        DCD     |OUTPUT|
|PPLAYER1INFO20|
        DCD     |PLAYER1INFO|
|EXITFLAG|
        DCD     &00000000                       ; Word r/w (referenced)

|ReadBytesFromSerial|
        MOV     R0,#SpecifyInputStream                           ; Function entry, (alters flags)
        MOV     R1,#InputStreamSerialPort
        SWI     OS_Byte

|BufferEmptyLoop|
        MOV     R0,#GetChar                         ; ="" (145)
        MOV     R1,#InputStreamSerialPort
        SWI     OS_Byte
        BCS     |BufferEmptyLoop|
        MOV     R4,R2 ; control x

|BufferEmptyLoop2|
        MOV     R0,#GetChar                         ; ="" (145)
        MOV     R1,#InputStreamSerialPort
        SWI     OS_Byte
        BCS     |BufferEmptyLoop2|
        MOV     R5,R2 ; control y

|BufferEmptyLoop3|
        MOV     R0,#GetChar                         ; ="" (145)
        MOV     R1,#InputStreamSerialPort
        SWI     OS_Byte
        BCS     |BufferEmptyLoop3|
        MOV     R6,R2 ; control bitmask

        MOV     R0,#SpecifyInputStream
        MOV     R1,#InputStreamKeyboard
        SWI     OS_Byte

        LDR     R7,|SERIALISMASTER|                  ; -> Word: &00000000
        CMP     R7,#0
        BNE     |READASMASTER|

        LDR     R7,|BUFFER|                  ; -> Word: &0001516C
        LDR     R8,[R7,#4]
        CMP     R8,#2
        BNE     |READASMASTER|

        LDR     R8,[R7,#8]
        ADD     R8,R8,#4
        STR     R8,[R7,#8]

|READASMASTER|
        LDR     R7,|SERIALISMASTER|                  ; -> Word: &00000000
        CMP     R7,#0
        BNE     |READASMASTER2|

        LDR     R7,|BUFFER|                  ; -> Word: &0001516C
        LDR     R8,[R7,#4]
        CMP     R8,#1
        BNE     |READASMASTER2|

        LDR     R8,[R7,#8]
        ADD     R8,R8,#4
        STR     R8,[R7,#8]

        MOV     R7,R4,LSL #24
        ADD     R7,R7,R5,LSL #16
        TST     R6,#4
        ADDNE   R7,R7,#1
        TST     R6,#2
        ADDNE   R7,R7,#2
        TST     R6,#1
        ADDNE   R7,R7,#4
        STR     R7,[R8,#-4]

|READASMASTER2|
        LDR     R7,|SERIALISMASTER|                  ; -> Word: &00000000
        CMP     R7,#1
        BNE     |READASSLAVE|

        TST     R6,#AircraftSerialBitMaster      ; ="" (128)
        BEQ     |READASSLAVE|

        LDR     R7,|BUFFER|                  ; -> Word: &0001516C
        MOV     R8,#0
        STR     R8,[R7,#4]

|READASSLAVE|
        MOV     PC,R14                          ; Function exit, Ends

|BUFFER|
        DCD     |REPLAYOVERFLOW|
        DCD     &000511D8                       ;~~ Word -/-
        DCD     &00000000                       ;~ Word -/-

|WriteBytesToSerial|
        LDR     R0,[R11,#AircraftSerialBitMask]                  ; =152, Function entry, (alters flags)
        BIC     R0,R0,#AircraftSerialBitMaster           ; ="" (128)
        STR     R0,[R11,#AircraftSerialBitMask]                  ; =152

        LDR     R0,|SERIALISMASTER|                  ; -> Word: &00000000
        CMP     R0,#0
        BNE     |WRITEASMASTER|

        LDR     R0,|BUFFER|                  ; -> Word: &0001516C
        LDR     R0,[R0,#4]
        CMP     R0,#2
        BEQ     |WRITEASMASTER|

        LDR     R0,[R11,#AircraftSerialBitMask]                  ; =152
        ADD     R0,R0,#AircraftSerialBitMaster           ; ="" (128)
        STR     R0,[R11,#AircraftSerialBitMask]                  ; =152

|WRITEASMASTER|
        MOV     R0,#SpecifyOutputStream
        MOV     R1,#OutputStreamEnableSerialPort :OR: OutputStreamDisableVDU
        SWI     OS_Byte

        LDR     R0,[R11,#AircraftCtrlX]                  ; =144
        ADD     R0,R0,#AircraftSerialCentre                      ; ="x" (120)
        SWI     OS_WriteC ; joystick x?

        LDR     R0,[R11,#AircraftCtrlY]                  ; =148
        ADD     R0,R0,#AircraftSerialCentre                      ; ="x" (120)
        SWI     OS_WriteC ; joystick y?

        LDR     R0,[R11,#AircraftSerialBitMask]                  ; =152
        SWI     OS_WriteC ; other state?

        MOV     R0,#SpecifyOutputStream
        MOV     R1,#0 ; Disable serial driver and enable VDU driver
        SWI     OS_Byte

        MOV     PC,R14                          ; Function exit, Ends

|PPICMAP5|
        DCD     |PICMAP|
|RETFROMINITBOTHPLAYERCOORDSNANGLE|
        DCD     &00000000                       ; Word r/w (referenced)
|PPLAYER1OR2INFO|
        DCD     &00000000                       ; Word r/w (referenced)
|RETURNADDR22|
        DCD     &00000000                       ; Word r/w (referenced)
|PDEMOSTATUS2|
        DCD     |DEMOSTATUS|
|CAMERAZOOMCOUNTDOWN|
        DCD     &00000000                       ; Word r/w (referenced)
|P3ENABLETARGETVIEW|
        DCD     |ENABLETARGETVIEW|
|PDRAWFULLFRONTVIEWCOUNT2|
        DCD     |DRAWFULLFRONTVIEWCOUNT|

|SERVICECAMERAZOOM|
        LDR     R0,|CAMERAZOOMCOUNTDOWN|             ; -> Word: &00000000, Function entry, (alters flags)
        CMP     R0,#0
        MOVLT   PC,R14                          ; Function exit if LT

        STMFD   R13!,{R0-R12,R14}

        LDR     R0,|CAMERAZOOMCOUNTDOWN|             ; -> Word: &00000000
        SUBS    R0,R0,#1
        STR     R0,|CAMERAZOOMCOUNTDOWN|             ; -> Word: &00000000

        LDR     R0,|PPLAYER2INFO17|                  ; -> Word: &00019CB0
        LDR     R1,|PPLAYER1INFO20|                  ; -> Word: &00019AA4

        BPL     |CONTINUEZOOMIN|

        ; Player 2
        LDR     R2,[R0,#PlayerAircraftToView]               ; =264
        CMP     R2,#CamOtherPlayer                         ; =21
        STREQ   R0,[R0,#PlayerAircraftToViewPtr]            ; =272
        MOVEQ   R2,#CamThisPlayer                          ; =20
        STREQ   R2,[R0,#PlayerAircraftToView]               ; =264

        ; Player 1
        LDR     R2,[R1,#PlayerAircraftToView]               ; =264
        CMP     R2,#CamOtherPlayer                         ; =21
        STREQ   R1,[R1,#PlayerAircraftToViewPtr]            ; =272
        MOVEQ   R2,#CamThisPlayer                          ; =20
        STREQ   R2,[R1,#PlayerAircraftToView]               ; =264

        LDR     R0,|PDRAWFULLFRONTVIEWCOUNT2|               ; -> Word: &00016268
        MOV     R1,#2
        STR     R1,[R0,#0]

        LDMFD   R13!,{R0-R12,R14}
        MOV     PC,R14                          ; Function exit, Ends

|CONTINUEZOOMIN|
        ; r0 = player 2
        ; r1 = player 1
        BL      |PLAYERZOOMIN|

        MOV     R0,R1
        BL      |PLAYERZOOMIN|

        LDMFD   R13!,{R0-R12,R14}
        MOV     PC,R14                          ; Function exit, Ends

|PLAYERZOOMIN|
        ; r0 = player
        ADD     R12,R0,#PlayerHighCoord                  ; =&1C8, Function entry, (alters flags)
        LDMIA   R12,{R2-R11} ; get x,y,z coordinates, y,x angles, vector, rotations

        SUB     R2,R2,R7 ; modify x,y,z coordinates
        SUB     R3,R3,R8
        SUB     R4,R4,R9

        SUB     R5,R5,R10 ; modify y,x angles
        ADD     R6,R6,R11

        CMP     R5,#FullRotation:SHL:AngleShift                      ; =&5A0000
        SUBGT   R5,R5,#FullRotation:SHL:AngleShift                   ; =&5A0000

        CMP     R6,#FullRotation:SHL:AngleShift                      ; =&5A0000
        SUBGT   R6,R6,#FullRotation:SHL:AngleShift                   ; =&5A0000

        CMP     R5,#0
        ADDLT   R5,R5,#FullRotation:SHL:AngleShift                   ; =&5A0000

        CMP     R6,#0
        ADDLT   R6,R6,#FullRotation:SHL:AngleShift                   ; =&5A0000

        STMIA   R12,{R2-R6} ; store updated x,y,z coordinates, y,x angles

        LDR     R12,[R0,#PlayerGhostPlane]                  ; =268
        STR     R5,[R12,#AircraftHeading]
        STR     R6,[R12,#AircraftPitch]

        ADD     R12,R12,#AircraftCoord                    ; =20
        STMIA   R12,{R2-R4} ; store modified coordinates
        SUB     R12,R12,#AircraftCoord                    ; =20

        MOV     R2,#ViewInside
        STR     R2,[R12,#AircraftViewIn]                  ; =44

        MOV     R3,#QuarterFront
        STR     R3,[R12,#AircraftViewQuarter]                  ; =36
        STR     R3,[R12,#AircraftViewAngle]                  ; =40
        STR     R3,[R12,#AircraftThrottle]                  ; =48

        MOV     PC,R14                          ; Function exit, Ends

|INITBOTHPLAYERCOORDSNANGLE|
        LDR     R0,|PPICMAP5|                  ; -> Word: &00017258, Function entry, (alters flags)
        LDR     R0,[R0,#0]
        CMP     R0,#0
        MOVNE   PC,R14                          ; Function exit if NE

        LDR     R0,|P3ENABLETARGETVIEW|                  ; -> Word: &00011434
        LDR     R0,[R0,#0]
        CMP     R0,#0
        MOVNE   PC,R14                          ; Function exit if NE

        ; Not target view
        LDR     R0,|PDEMOSTATUS2|                  ; -> Word: &00015DC4
        LDR     R0,[R0,#0]
        CMP     R0,#0
        MOVNE   PC,R14                          ; Function exit if NE

        ; Not demo
        STR     R14,|RETFROMINITBOTHPLAYERCOORDSNANGLE|                 ; -> Word: &00000000

        LDR     R0,|PPLAYER2INFO17|                  ; -> Word: &00019CB0
        STR     R0,|PPLAYER1OR2INFO|                  ; -> Word: &00000000
        BL      |INITPLAYERCOORDSNANGLE|

        LDR     R0,|PPLAYER1INFO20|                  ; -> Word: &00019AA4
        STR     R0,|PPLAYER1OR2INFO|                  ; -> Word: &00000000
        BL      |INITPLAYERCOORDSNANGLE|

        LDR     R14,|RETFROMINITBOTHPLAYERCOORDSNANGLE|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|INITPLAYERCOORDSNANGLE|
        STR     R14,|RETURNADDR22|                 ; -> Word: &00000000, Function entry, (alters flags)

        LDR     R0,|PPLAYER1OR2INFO|                  ; -> Word: &00000000
        ADD     R1,R0,#AircraftCoord                      ; =20
        LDMIA   R1,{R1,R2}

        ADD     R3,R0,#PlayerHighCoord                   ; =&1C8
        LDMIA   R3,{R3,R4} ; get x,y coordinates

        SUB     R11,R3,R1
        SUB     R12,R4,R2
        BL      |FINDANGLE| ; R11,R12 = length of sides, returns angle in R1

        SUBS    R1,R1,#QuarterTurn                   ; =&5A0
        ADDMI   R1,R1,#FullRotation                   ; =&1680

        LDR     R0,|PPLAYER1OR2INFO|                  ; -> Word: &00000000
        LDR     R2,[R0,#PlayerGhostPlane]                   ; =268
        SUB     R5,R2,R1,LSL #AngleShift
        CMP     R5,#HalfTurn:SHL:AngleShift                      ; =&2D0000
        RSBGT   R5,R5,#FullRotation:SHL:AngleShift                   ; =&5A0000
        CMN     R5,#HalfTurn:SHL:AngleShift                      ; =&2D0000
        RSBLT   R5,R5,#FullRotation:SHL:AngleShift                   ; =&5A0000
        CMP     R5,#FullRotation:SHL:AngleShift                      ; =&5A0000
        SUBGT   R5,R5,#FullRotation:SHL:AngleShift                   ; =&5A0000
        MOV     R5,R5,ASR #7
        STR     R5,[R0,#PlayerRotationY]                   ; =488

        MVN     R5,#&02,22                      ; =&800
        STR     R5,[R0,#PlayerRotationX]                   ; =492

        ADD     R1,R0,#AircraftCoord                      ; =20
        LDMIA   R1,{R1-R3}

        ADD     R4,R0,#PlayerHighCoord                   ; =&1C8
        LDMIA   R4,{R4-R6} ; get x,y,z coordinates

        SUB     R1,R4,R1 ; modify x,y,z coordinates
        SUB     R2,R5,R2
        SUB     R3,R6,R3

        MOV     R1,R1,ASR #7
        MOV     R2,R2,ASR #7
        MOV     R3,R3,ASR #7

        ADD     R7,R0,#&200
        SUB     R7,R7,#(&200 - PlayerToCameraVec)
        STMIA   R7,{R1-R3}

        LDR     R1,[R0,#PlayerGhostPlane]                   ; =268
        STR     R1,[R0,#PlayerAircraftToViewPtr]                   ; =272

        MOV     R1,#CamOtherPlayer                         ; =21
        STR     R1,[R0,#PlayerAircraftToView]                   ; =264

        LDR     R14,|RETURNADDR22|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|PSPLITSCREEN12|
        DCD     |SPLITSCREEN|
|PXANGLE|
        DCD     |XANGLE|
|P2ROTATIONMATRIX|
        DCD     |ROTATIONMATRIX|
|OBJMESHINDEX|
        DCD     &00000000                       ; Word r/w (referenced)
|OBJMESHADDR|
        DCD     &00000000                       ; Word r/w (referenced)
|OBJMESHSTARTADDR|
        DCD     &0004D098                       ; Word r/- (referenced)
|OBJMESHNUMBER|
        DCD     &00000000                       ; Word r/w (referenced)
|INITOBJMESHNUMBER|
        DCD     &0000009F                       ; Word r/- (referenced)
|OBJ3D|
        DCD     MemObj3DAddrArray                       ; Word r/- (referenced)
|RETFROMDRAWAIRCRAFTWITHSHADOW|
        DCD     &00000000                       ; Word r/w (referenced)
|PLANEMESHADDRESSES|
        DCD     &000400C8 ; TIGER MOTH    (OWN PLANE)
        DCD     &00000000
        DCD     &000403C4 ; FOKKER V7 TWIN
        DCD     &00041264 ; FOKKER EINDECKER IV
        DCD     &00041828 ; ALBATROS DIII SCOUT
        DCD     &000409C8 ; GOTHA G IV BOMBER
        DCD     &000414DC ; FOKKER VIII TRIPLANE
        DCD     &00047338 ; FOKKER DE5 BIPLANE
        DCD     &00046FAC ; FOKKER V3 TRIENGINE
        DCD     &00046B94 ; CARGO AIRCRAFT
        DCD     &0004AE74 ; JET FIGHTER
        DCD     &00000000                       ;~ Word -/-
|SHADOWMESHADDRESSES|
        DCD     &00040DB4 ; TIGER MOTH    (OWN PLANE)
        DCD     &00000000
        DCD     &00040E7C ; FOKKER V7 TWIN
        DCD     &0004100C ; FOKKER EINDECKER IV
        DCD     &000410D4 ; ALBATROS DIII SCOUT
        DCD     &00040F44 ; GOTHA G IV BOMBER
        DCD     &0004119C ; FOKKER VIII TRIPLANE
        DCD     &0004A7D8 ; FOKKER DE5 BIPLANE
        DCD     &0004A8A0 ; FOKKER V3 TRIENGINE
        DCD     &0004A968 ; CARGO AIRCRAFT
        DCD     &0004A8A0 ; JET FIGHTER
        DCD     &00000000                       ;~ Word -/-

|DRAWAIRCRAFTWITHSHADOW|
        ; R0-R2 = angles of rotation
        ; R3-R5 = coordinates
        ; R12 = object mesh number
        STR     R14,|RETFROMDRAWAIRCRAFTWITHSHADOW|                 ; -> Word: &00000000, Function entry, (alters flags)
        STR     R12,|OBJMESHINDEX|                 ; -> Word: &00000000
        STMFD   R13!,{R0-R5,R12}
        STMFD   R13!,{R3-R5}

        LDR     R12,|PXANGLE|                 ; -> Word: &0001D34C
        STR     R2,[R12,#AircraftPitch]
        STR     R1,[R12,#AircraftHeading]
        STR     R0,[R12,#AircraftRoll]

        BL      |MAKEROTATIONMATRIX|

        LDR     R12,|OBJMESHINDEX|                 ; -> Word: &00000000
        ADR     R0,|PLANEMESHADDRESSES|                  ; -> Word: &000400C8
        ADD     R4,R0,R12,LSL #BytesPerAddressLog2
        LDR     R4,[R4,#0] ; get object mesh address

        LDR     R0,|OBJMESHADDR|                  ; -> Word: &00000000

        LDR     R12,|OBJ3D|                 ; -> Word: MemObj3DAddrArray
        LDR     R11,|OBJMESHNUMBER|                 ; -> Word: &00000000
        ADD     R12,R12,R11,LSL #BytesPerAddressLog2
        ADD     R11,R11,#1
        STR     R11,|OBJMESHNUMBER|                 ; -> Word: &00000000
        STR     R0,[R12,#0] ; store object mesh address

        LDMIA   R4!,{R1-R3,R5-R9} ; copy aircraft mesh header
        STMIA   R0!,{R1-R3,R5-R9}

        LDR     R14,|P2ROTATIONMATRIX|                 ; -> Word: &0001D31C
        ; R3 = no. of vertices-1
|MATRIXMULTIPLYLOOP|
        LDR     R5,[R4,#VertX]
        LDR     R6,[R4,#VertZ]
        LDMIA   R14!,{R9-R12}

        MUL     R7,R5,R12
        MOV     R7,R7,ASR #12
        MUL     R8,R6,R11
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#VertX]

        MUL     R7,R6,R9
        MOV     R7,R7,ASR #12
        MUL     R8,R5,R10
        ADD     R6,R7,R8,ASR #12

        LDR     R5,[R4,#VertY]
        LDMIA   R14!,{R9-R12}

        MUL     R7,R5,R12
        MOV     R7,R7,ASR #12
        MUL     R8,R6,R11
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#VertY]

        MUL     R7,R6,R9
        MOV     R7,R7,ASR #12
        MUL     R8,R5,R10
        ADD     R6,R7,R8,ASR #12
        STR     R6,[R0,#VertZ]

        LDR     R5,[R0,#VertX]
        LDR     R6,[R0,#VertY]
        LDMIA   R14,{R9-R12}

        MUL     R7,R6,R9
        MOV     R7,R7,ASR #12
        MUL     R8,R5,R10
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#VertY]

        MUL     R7,R5,R12
        MOV     R7,R7,ASR #12
        MUL     R8,R6,R11
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#VertX]

        SUB     R14,R14,#&20                    ; =" " (32)
        ADD     R0,R0,#BytesPerVert                      ; =12
        ADD     R4,R4,#BytesPerVert                      ; =12
        SUBS    R3,R3,#1
        BPL     |MATRIXMULTIPLYLOOP|

        ; R2 = no. of primitives-1
|COPYAIRCRAFTPRIMITIVESLOOP|
        LDMIA   R4!,{R5-R8} ; load primitive
        STMIA   R0!,{R5-R8} ; store primitive
        SUBS    R2,R2,#1
        BPL     |COPYAIRCRAFTPRIMITIVESLOOP|

        STR     R0,|OBJMESHADDR|                  ; -> Word: &00000000

        LDR     R1,|NUMOBJMINUS1|                  ; -> Word: &000001DE
        ADD     R1,R1,#1
        STR     R1,|NUMOBJMINUS1|                  ; -> Word: &000001DE

        LDR     R0,|POBJARRAY2|                  ; -> Word: MemObjArray
        MOV     R2,R1,LSL #ObjDataSizeALog2
        ADD     R2,R2,R1,LSL #ObjDataSizeBLog2
        ADD     R0,R0,R2 ; address of object to init

        LDR     R7,|OBJMESHNUMBER|                  ; -> Word: &00000000
        SUB     R7,R7,#1
        MOV     R8,#ObjDrawStateDrawIfNear
        MOV     R9,#&0A ; ObjDist
        LDMFD   R13!,{R10-R12} ; load object coordinates
        STMIA   R0!,{R7-R12} ; store mesh no., draw state, dist & coords

        ADR     R1,|OBJSTATICDATA|     ; -> Word array: &00047868
        LDMIA   R1,{R2-R7}
        STMIA   R0,{R2-R7} ; copy second half

        LDMFD   R13!,{R0-R5,R12}
        ; R12 = Object number
        STMFD   R13!,{R3,R4}

        ADR     R0,|SHADOWMESHADDRESSES|                  ; -> Word: &00040DB4
        ADD     R4,R0,R12,LSL #BytesPerAddressLog2 ; object number
        LDR     R4,[R4,#0] ; get shadow mesh address

        LDR     R0,|OBJMESHADDR|                  ; -> Word: &00000000

        LDR     R12,|OBJ3D|                 ; -> Word: MemObj3DAddrArray
        LDR     R11,|OBJMESHNUMBER|                 ; -> Word: &00000000
        ADD     R12,R12,R11,LSL #BytesPerAddressLog2
        ADD     R11,R11,#1
        STR     R11,|OBJMESHNUMBER|                 ; -> Word: &00000000
        STR     R0,[R12,#0] ; store object mesh address

        LDMIA   R4!,{R1-R3,R5-R9} ; copy shadow mesh header
        STMIA   R0!,{R1-R3,R5-R9}

        LDR     R14,|P2ROTATIONMATRIX|                 ; -> Word: &0001D31C
        ; R3 = no. of vertices-1
|MATRIXMULTIPLYLOOP2|
        LDR     R5,[R4,#VertX] ; get
        LDR     R6,[R4,#VertZ]
        LDMIA   R14!,{R9-R12} ; get rotation coefficients

        MUL     R7,R5,R12
        MOV     R7,R7,ASR #12
        MUL     R8,R6,R11
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#VertX]

        MUL     R7,R6,R9
        MOV     R7,R7,ASR #12
        MUL     R8,R5,R10
        ADD     R6,R7,R8,ASR #12

        LDR     R5,[R4,#VertY]
        LDMIA   R14!,{R9-R12} ; get rotation coefficients

        MUL     R7,R5,R12
        MOV     R7,R7,ASR #12
        MUL     R8,R6,R11
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#VertY]

        MUL     R7,R6,R9
        MOV     R7,R7,ASR #12
        MUL     R8,R5,R10
        ADD     R6,R7,R8,ASR #12
        STR     R6,[R0,#VertZ]

        LDR     R5,[R0,#VertX]
        LDR     R6,[R0,#VertY]
        LDMIA   R14,{R9-R12} ; get rotation coefficients

        MUL     R7,R6,R9
        MOV     R7,R7,ASR #12
        MUL     R8,R5,R10
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#VertY]

        MUL     R7,R5,R12
        MOV     R7,R7,ASR #12
        MUL     R8,R6,R11
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#VertX]

        MOV     R8,#0
        STR     R8,[R0,#VertZ]

        SUB     R14,R14,#&20                    ; =" " (32)
        ADD     R0,R0,#BytesPerVert                      ; =12
        ADD     R4,R4,#BytesPerVert                      ; =12
        SUBS    R3,R3,#1
        BPL     |MATRIXMULTIPLYLOOP2|

        ; R2 = no. of primitives-1
|COPYSHADOWPRIMITIVESLOOP|
        LDMIA   R4!,{R5-R8} ; load primitive
        STMIA   R0!,{R5-R8} ; store primitive
        SUBS    R2,R2,#1
        BPL     |COPYSHADOWPRIMITIVESLOOP|

        STR     R0,|OBJMESHADDR|                  ; -> Word: &00000000

        LDR     R1,|NUMOBJMINUS1|                  ; -> Word: &000001DE
        ADD     R1,R1,#1
        STR     R1,|NUMOBJMINUS1|                  ; -> Word: &000001DE

        LDR     R0,|POBJARRAY2|                  ; -> Word: MemObjArray
        MOV     R2,R1,LSL #ObjDataSizeALog2
        ADD     R2,R2,R1,LSL #ObjDataSizeBLog2
        ADD     R0,R0,R2

        LDR     R7,|OBJMESHNUMBER|                  ; -> Word: &00000000
        SUB     R7,R7,#1
        MOV     R8,#ObjDrawStateDrawIfNear
        MOV     R9,#&0A ; ObjDist
        LDMFD   R13!,{R10,R11} ; ObjCoordX, ObjCoordY
        MOV     R12,#0 ; ObjCoordZ
        STMIA   R0!,{R7-R12}

        ADR     R1,|OBJSTATICDATA|                  ; -> Word array: &00047868
        LDMIA   R1,{R2-R7}
        MOV     R6,#0 ; ObjCullBackface for shadow
        STMIA   R0,{R2-R7}

        LDR     R14,|RETFROMDRAWAIRCRAFTWITHSHADOW|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|OBJSTATICDATA|
        DCD     &00047868
        DCD     &00000000
        DCD     &000A0EEB ; ObjMaxDist
        DCD     &000007D0 ; ObjFieldOfView
        DCD     &00000001 ; ObjCullBackface
        DCD     &0000EA60 ; ObjClipDistFactor

|INITOBJMESHADDR|
        LDR     R11,|OBJMESHSTARTADDR|                 ; -> Word: &0004D098, Function entry, (alters flags)
        STR     R11,|OBJMESHADDR|                 ; -> Word: &00000000

        LDR     R11,|INITOBJMESHNUMBER|                 ; -> Word: &0000009F
        STR     R11,|OBJMESHNUMBER|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|MOVETARGETS|
        ADR     R11,|OBJSTATICDATA|                 ; -> Word array: &00047868, Function entry, (alters flags)

        LDR     R12,|PTARGETDATAARRAY4|                 ; -> Word: &0001462C
        LDR     R12,[R12,#0]

        LDR     R0,|POBJARRAY2|                  ; -> Word: MemObjArray
        LDR     R1,|ANOTHERNUMOBJMINUS1|                  ; -> Word: &000001DE
        SUB     R1,R1,#&13                      ; =19
        MOV     R2,R1,LSL #ObjDataSizeALog2
        ADD     R2,R2,R1,LSL #ObjDataSizeBLog2
        ADD     R0,R0,R2 ; output address

        MOV     R1,#(NumPracticeTargets-1)        ; =19

|TARGETLOOP3|
        LDR     R5,[R12,#TargetHitpoints]                  ; =28
        CMN     R5,#0
        MOVLT   R5,#MESH_RUBBISH
        BLT     |NOTRAINSMOKE|

        LDR     R5,[R12,#TargetType]                  ; =24
        CMP     R5,#TTYPE_AIRSHIP
        BLT     |NOLOOKUP|

        ADR     R2,|TYPETOGRAPHICNUM|                  ; -> Word: &4F4E4948
        SUB     R5,R5,#TTYPE_AIRSHIP
        ADD     R2,R2,R5
        LDRB    R5,[R2,#0]

|NOLOOKUP|
        ; r5 = mesh number
        LDR     R3,|PPLAYERNUM6|                  ; -> Word: &0001203C
        LDR     R3,[R3,#0]
        CMP     R3,#1
        BEQ     |NOTRAINSMOKE|

        CMP     R5,#MESH_TRAIN
        CMPNE   R5,#MESH_TANK
        CMPNE   R5,#MESH_AIRSHIP
        BNE     |NOTRAINSMOKE|

        ; Move the target
        MOV     R3,#0
        MOV     R4,#0
        CMP     R5,#MESH_TRAIN
        MOVEQ   R4,#TrainSpeed                 ; ="-" (45)

        CMP     R5,#MESH_TANK
        MVNEQ   R3,#TankSpeed                  ; =15

        CMP     R5,#MESH_AIRSHIP
        MVNEQ   R4,#AirshipSpeed               ; =20

        LDR     R2,[R12,#TargetCoordX]
        SUB     R2,R2,R3
        STR     R2,[R12,#TargetCoordX]

        LDR     R2,[R12,#TargetCoordY]
        SUB     R2,R2,R4
        STR     R2,[R12,#TargetCoordY]

        CMP     R5,#MESH_TRAIN
        BNE     |NOTRAINSMOKE|

        ; Train
        LDR     R2,|P3COUNT0TO2|                  ; -> Word: &00011FB8
        LDR     R2,[R2,#0]
        CMP     R2,#1
        BNE     |NOTRAINSMOKE|

        STMFD   R13!,{R0-R12,R14}
        LDMIA   R12,{R2,R3}
        SUB     R3,R3,#&0B,26                   ; =&2C0
        MVN     R2,R2,LSL #10
        MVN     R3,R3,LSL #10
        MOV     R4,#&01,14                      ; =&40000
        MOV     R5,#SmokeTypeQuickBlack
        BL      |ADDSMOKEGEN|
        LDMFD   R13!,{R0-R12,R14}

|NOTRAINSMOKE|
        ; r5 = mesh number
        ; r12 = pointer to target
        STR     R5,[R0,#ObjMesh]
        CMP     R5,#MESH_OIL_TANKER
        CMPNE   R5,#MESH_AIRSHIP

        LDMIA   R12,{R2-R4} ; get target coordinates
        ADD     R0,R0,#ObjCoord           ; =12
        STMIA   R0!,{R2-R4} ; store target coordinates

        LDMIA   R11,{R2-R7}
        ; Override most values for the oil tanker and airship
        MOVEQ   R2,#&09,12                      ; =&900000
        MOVEQ   R4,#&09,12 ; ObjMaxDist =&900000
        MOVEQ   R5,#&1800  ; ObjFieldOfView
        MOVEQ   R7,#&32000 ; ObjClipDistFactor
        STMIA   R0!,{R2-R7}

        ADD     R12,R12,#1:SHL:BytesPerTargetLog2                   ; =" " (32)
        SUBS    R1,R1,#1
        BPL     |TARGETLOOP3|

        MOV     PC,R14                          ; Function exit, Ends

|TYPETOGRAPHICNUM|
        DCB MESH_AIRSHIP, MESH_BARRAGE_BALLOON, MESH_CONTROL_TERMINAL, MESH_OIL_TANKER, MESH_GUN_BOAT, MESH_TRAIN, MESH_GOTHA_G_IV_BOMBER, MESH_FOKKER_EINDECKER_IV, MESH_FOKKER_V7_TWIN, MESH_FOKKER_V3_TRIENGINE, MESH_CARGO_AIRCRAFT, MESH_YACHT, MESH_RAILWAY_STATION, MESH_BRIDGE, MESH_FACTORY, MESH_AIRCRAFT_CARRIER, MESH_JET_FIGHTER_TARGET,0,0,0

|PTARGETDATAARRAY4|
        DCD     |TARGETDATAARRAY|
|P3COUNT0TO2|
        DCD     |COUNT0TO2|
|RETURNADDR9|
        DCD     &00000000                       ; Word r/w (referenced)
|PPLAYERNUM6|
        DCD     |PLAYERNUM|
|FIRSTOBJTOCALCVIS|
        DCD     &00000000                       ; Word r/w (referenced)
|POBJARRAY2|
        DCD     MemObjArray                       ; Word r/- (referenced)
|NUMOBJMINUS1|
        DCD     &000001DE                       ; Word r/w (referenced)
|ANOTHERNUMOBJMINUS1|
        DCD     &000001DE                       ; Word r/- (referenced)
|CALCOBJVISLOOPSTEP|
        DCD     CalcObjVisInterval              ; Word r/w (referenced)
|P5PREVENTTIMESKIP|
        DCD     |PREVENTTIMESKIP|
|TEMPSTACKP|
        DCD     &00000000                       ; Word r/w (referenced)
|CAMERAPOSX|
        DCD     &00000000                       ; Word array r/w (referenced)
|CAMERAPOSY|
        DCD     &00000000                       ;~~~ Word array r/w (referenced)
|CAMERAPOSZ|
        DCD     &00000000                       ;~~~ Word array r/w (referenced)
|LINEDATA2|
        DCD     &00000000                       ;~~~ Word array r/w (referenced)
|PHONOLULUBLUE|
        DCD     |HONOLULUBLUE|
|PFRAMEBUFFER98|
        DCD     |FRAMEBUFFER98|
|PFRAMEBUFFER99|
        DCD     |FRAMEBUFFER99|
|CLEARFRAMEENDOFFSET|
        DCD     |L00001D10|
|PXANGLE2|
        DCD     |XANGLE|
|PMAXCOORDY|
        DCD     |MAXCOORDY|
|PMAXCOORDY2|
        DCD     |MAXCOORDY2|
|FRAMEBUFFER97|
        DCD     &00000000                       ;~~~ Word array -/w (referenced)
|L0000B6B4.5_byte_Time|
        DCB     &0000000000                     ; 5 byte Time r/w (referenced)
|L0000B6B9.5_byte_Time|
        DCB     &00,&00,&00
        DCD     &00000000                       ; Word r/w (referenced)
|CLIPDIST|
        DCD     &00000080                       ; Word r/w (referenced)
|UNUSEDCLIPDIST|
        DCD     &00000000                       ; Word r/w (referenced)
|PGRAPHICSDETAIL|
        DCD     |GRAPHICSDETAIL|
|PGRAPHICSDETAILCOPY|
        DCD     |GRAPHICSDETAILCOPY|
|MAXCLIPDIST|
        DCD     &00000200                       ; Word r/- (referenced)
|PSPLITSCREEN13|
        DCD     |SPLITSCREEN|

|DRAWSCENE|
        ; r0 = frame buffer
        ; r4-r6 = camera coordinates
        ; r10 = pointer to source pixel data
        ; r11 = column at which to stop clearing
        ; r12 = line at which to stop clearing
        STR     R14,|RETURNADDR9|                 ; -> Word: &00000000, Function entry, (alters flags)
        STR     R10,|LINEDATA2|                 ; -> Word array: &00000000
        SUB     R12,R12,#1

        LDR     R10,|PMAXCOORDY|                 ; -> Word array: &0001DFA8
        STR     R12,[R10,#0] ; MAXCOORDY
        STR     R11,[R10,#4] ; MAXCOORDX

        LDR     R10,|PMAXCOORDY2|                 ; -> Word array: &0001E994
        STR     R12,[R10,#0] ; MAXCOORDY2
        STR     R11,[R10,#4] ; MAXCOORDX2

        ADD     R12,R12,#1
        MOV     R11,R12,LSL #RowStrideALog2
        ADD     R11,R11,R12,LSL #RowStrideBLog2
        STR     R11,|CLEARFRAMEENDOFFSET|                 ; -> Word array: &00012E80

        LDR     R12,|PFRAMEBUFFER98|                 ; -> Word array: &0001DFC8
        STR     R0,[R12,#0]

        LDR     R12,|PFRAMEBUFFER99|                 ; -> Word array: &0001E9A0
        STR     R0,[R12,#0]

        STR     R0,|FRAMEBUFFER97|                  ; -> Word array: &00000000

        LDR     R14,|PXANGLE2|                 ; -> Word array: &0001D34C
        STMIA   R14,{R1-R3} ; get camera position

        STR     R4,|CAMERAPOSX|                  ; -> Word array: &00000000
        STR     R5,|CAMERAPOSY|                  ; -> Word array: &00000000
        STR     R6,|CAMERAPOSZ|                  ; -> Word array: &00000000

        XABSDIFF R2,R2,#(UnitsPerDegree*272)     ; =&1100
        CMP     R2,#WIDTH
        LDRLT   R0,|PHONOLULUBLUE|                  ; -> Word array: &0001EF68
        LDRGE   R0,|LINEDATA2|                  ; -> Word array: &00000000
        LDMIA   R0,{R0-R9}

        LDR     R10,|PFRAMEBUFFER98|                 ; -> Word array: &0001DFC8
        LDR     R10,[R10,#0]

        LDR     R11,|CLEARFRAMEENDOFFSET|                 ; -> Word array: &00012E80
        ADD     R11,R11,R10

        LDR     R12,|PSPLITSCREEN13|                 ; -> Word: &00016B28
        LDR     R12,[R12,#0]
        CMP     R12,#0
        BNE     |CLEARSERIALGAMELOOP|

|CLEARNOSERIALLOOP|
count SETA 0
        WHILE count < WIDTH/PixelCopyChunk

        STMIA   R10!,{R0-R9}

count SETA count + 1
        WEND

        CMP     R10,R11
        BLT     |CLEARNOSERIALLOOP|

        B       |FINISHEDCLEAR|                     ; Ends

|CLEARSERIALGAMELOOP|
count SETA 0
        WHILE count < (WIDTH-DASHBOARDWIDTH)/PixelCopyChunk

        STMIA   R10!,{R0-R9}

count SETA count + 1
        WEND

        ADD     R10,R10,#DASHBOARDWIDTH                    ; ="P" (80)
        CMP     R10,R11
        BLT     |CLEARSERIALGAMELOOP|

|FINISHEDCLEAR|
        LDR     R0,|PGRAPHICSDETAIL|                  ; -> Word: &000166AC
        LDR     R0,[R0,#0]
        LDR     R1,|PGRAPHICSDETAILCOPY|                  ; -> Word: &0001F968
        STR     R0,[R1,#0]

        LDR     R1,|P5PREVENTTIMESKIP|                  ; -> Word: &00015714
        LDR     R0,[R1,#0]
        CMP     R0,#0
        BEQ     |ALLOWTIMESKIP|

        ; No time skip is allowed
        MOV     R0,#0
        STR     R0,|FIRSTOBJTOCALCVIS|                  ; -> Word: &00000000

        MOV     R0,#1
        STR     R0,|CALCOBJVISLOOPSTEP|                  ; -> Word: &00000005

|ALLOWTIMESKIP|
        BL      |MAKEROTATIONMATRIX|

        ADR     R1,|L0000B6B4.5_byte_Time|      ; -> 5 byte Time: &0000000000
        MOV     R4,#0
        STR     R4,[R1,#0]
        STR     R4,[R1,#4]
        MOV     R0,#WriteIntervalTimer
        SWI     OS_Word

        STR     R13,|TEMPSTACKP|                 ; -> Word: &00000000

        LDR     R13,|CALCOBJVISLOOPSTEP|                 ; -> Word: &00000005

        LDR     R0,|FIRSTOBJTOCALCVIS|                  ; -> Word: &00000000
        LDR     R1,|POBJARRAY2|                  ; -> Word: MemObjArray
        MOV     R2,R0,LSL #ObjDataSizeALog2
        ADD     R2,R2,R0,LSL #ObjDataSizeBLog2
        ADD     R1,R1,R2

        ADR     R4,|CAMERAPOSX|                  ; -> Word array: &00000000
        LDR     R2,|ANOTHERNUMOBJMINUS1|                  ; -> Word: &000001DE
|CULLFAROBJLOOP|
        LDR     R5,[R1,#ObjCoordX]                   ; =12
        LDR     R6,[R1,#ObjCoordY]                   ; =16

        LDR     R10,[R1,#ObjClipDistFactor]                  ; =44
        LDR     R8,|CLIPDIST|                  ; -> Word: &00000080
        MUL     R9,R8,R10
        MOV     R10,R9,ASR #8 ; final clipping distance

        LDMIA   R4,{R8,R9} ; get camera x,y
        ABSDIFF R11,R5,R8 ; thing x - cam x
        CMP     R11,R10 ; check x against clipping distance
        BGT     |OBJISNOTINVIEW| ; thing is too far from camera

        ABSDIFF R11,R6,R9 ; thing y - cam y
        CMP     R11,R10 ; check y against clipping distance
        BGT     |OBJISNOTINVIEW| ; thing is too far from camera

        SUB     R7,R6,R9
        SUB     R6,R5,R8
        LDR     R11,|XANGLE|                 ; -> Word array: &00000000
        BL      |ROTATE2DCOORD| ; output rotated R6,R7

        LDR     R8,[R4,#8] ; get camera z
        MOV     R3,R6 ; rotated x coord
        MOV     R6,R7 ; rotated y coord
        LDR     R7,[R1,#ObjCoordZ]                   ; =20
        SUB     R7,R7,R8
        LDR     R11,|YANGLE|                 ; -> Word array: &00000000
        BL      |ROTATE2DCOORD| ; output rotated R6,R7

        LDR     R9,[R1,#ObjFieldOfView]                   ; =36

        ABS     R3 ; rotated x coord
        SUB     R3,R3,R9

        ABS     R7 ; rotated z coord
        SUB     R7,R7,R9

        CMP     R3,R6 ; compare with rotated y
        BLT     |DRAWOBJ|

        CMP     R7,R6 ; compare with rotated y
        BLT     |DRAWOBJ|

|OBJISNOTINVIEW|
        MOV     R6,#ObjDrawStateCull
        STR     R6,[R1,#ObjDrawState]
        B       |CULLNEXTOBJ|                     ; Ends

|DRAWOBJ|
        MOV     R10,R4
        LDMIA   R1,{R3-R9}
        MOV     R4,R10
        LDMIA   R4,{R10-R12}

        ABSDIFF R6,R6,R10
        ABSDIFF R7,R7,R11
        ABSDIFF R8,R8,R12

        MOV     R6,R6,ASR #7
        MOV     R7,R7,ASR #7
        MOV     R8,R8,ASR #7

        MUL     R3,R6,R6
        MUL     R5,R7,R7
        ADD     R3,R3,R5
        MUL     R5,R8,R8
        ADD     R3,R3,R5

        LDR     R10,|UNUSEDCLIPDIST| ; bug?                ; -> Word: &00000000
        MOV     R3,R3,ASR #6
        MUL     R5,R3,R10 ; bug?

        LDR     R10,[R1,#ObjMaxDist] ; bug?        ; =32
        CMP     R3,R10 ; bug?

        MOV     R5,#ObjDrawStateDrawIfNear
        STR     R3,[R1,#ObjDist]
        STR     R5,[R1,#ObjDrawState]

|CULLNEXTOBJ|
        ADD     R0,R0,R13
        CMP     R13,#1
        ADDNE   R1,R1,#(BytesPerObj*CalcObjVisInterval)     ; ="" (240)
        ADDEQ   R1,R1,#BytesPerObj         ; ="0" (48)
        CMP     R0,R2
        BLE     |CULLFAROBJLOOP|

        LDR     R13,|TEMPSTACKP|                 ; -> Word: &00000000

        MOV     R0,#CalcObjVisInterval
        STR     R0,|CALCOBJVISLOOPSTEP|                  ; -> Word: &00000005

        LDR     R0,|ANOTHERNUMOBJMINUS1|                  ; -> Word: &000001DE
        LDR     R2,|NUMOBJMINUS1|                  ; -> Word: &000001DE
        CMP     R0,R2
        BEQ     |L0000BA94|

        LDR     R1,|POBJARRAY2|                  ; -> Word: MemObjArray
        MOV     R4,R0,LSL #ObjDataSizeALog2
        ADD     R4,R4,R0,LSL #ObjDataSizeBLog2
        ADD     R1,R1,R4

        ADR     R4,|CAMERAPOSX|                  ; -> Word array: &00000000
|OBJLOOP2|
        LDR     R5,[R1,#ObjCoordX]                   ; =12
        LDR     R6,[R1,#ObjCoordY]                   ; =16

        LDR     R10,[R1,#ObjClipDistFactor]                  ; =44
        LDR     R8,|CLIPDIST|                  ; -> Word: &00000080
        MUL     R9,R8,R10
        MOV     R10,R9,ASR #8 ; final clipping distance

        LDMIA   R4,{R8,R9} ; get camera x,y pos
        ABSDIFF R11,R5,R8
        CMP     R11,R10 ; check x against clipping distance
        BGT     |OBJISNOTINVIEW2|

        ABSDIFF R11,R6,R9 ; y distance
        CMP     R11,R10 ; check y against clipping distance
        BGT     |OBJISNOTINVIEW2|

        SUB     R7,R6,R9 ; y coord diff
        SUB     R6,R5,R8 ; x coord diff
        LDR     R11,|XANGLE|                 ; -> Word array: &00000000
        BL      |ROTATE2DCOORD| ; output rotated R6,R7

        LDR     R8,[R4,#8] ; get camera z pos
        MOV     R3,R6 ; rotated x
        MOV     R6,R7 ; rotated y
        LDR     R7,[R1,#ObjCoordZ]                   ; =20
        SUB     R7,R7,R8 ; ; z coord diff
        LDR     R11,|YANGLE|                 ; -> Word array: &00000000
        BL      |ROTATE2DCOORD| ; output rotated R6,R7

        LDR     R9,[R1,#ObjFieldOfView]                   ; =36

        ABS     R3 ; rotated x
        SUB     R3,R3,R9

        ABS     R7 ; rotated z
        SUB     R7,R7,R9

        CMP     R3,R6 ; compare with rotated y
        BLT     |DRAWOBJ2|

        CMP     R7,R6 ; compare with rotated y
        BLT     |DRAWOBJ2|

|OBJISNOTINVIEW2|
        MOV     R6,#ObjDrawStateCull
        STR     R6,[R1,#ObjDrawState]
        B       |CULLNEXTOBJ2|                     ; Ends

|DRAWOBJ2|
        MOV     R10,R4
        LDMIA   R1,{R3-R9}
        MOV     R4,R10
        LDMIA   R4,{R10-R12}

        ABSDIFF R6,R6,R10
        ABSDIFF R7,R7,R11
        ABSDIFF R8,R8,R12

        MOV     R6,R6,ASR #7
        MOV     R7,R7,ASR #7
        MOV     R8,R8,ASR #7

        MUL     R3,R6,R6 ; square
        MUL     R5,R7,R7 ; square
        ADD     R3,R3,R5

        MUL     R5,R8,R8 ; square
        ADD     R3,R3,R5

        LDR     R10,|UNUSEDCLIPDIST| ; bug?       ; -> Word: &00000000
        MOV     R3,R3,ASR #6
        MUL     R5,R3,R10 ; bug?

        LDR     R10,[R1,#ObjMaxDist]                  ; =32
        CMP     R3,R10
        MOV     R5,#ObjDrawStateDrawIfNear
        MOVGE   R3,#ObjDistMax
        STR     R3,[R1,#ObjDist]
        STR     R5,[R1,#ObjDrawState]

|CULLNEXTOBJ2|
        ADD     R0,R0,#1
        ADD     R1,R1,#BytesPerObj                      ; ="0" (48)
        CMP     R0,R2
        BLE     |OBJLOOP2|

|L0000BA94|
        BL      |DRAWSKY|

        LDR     R11,|POBJARRAY2|                 ; -> Word: MemObjArray
        LDR     R1,|NUMOBJMINUS1|                  ; -> Word: &000001DE
        LDR     R3,|PGRAPHICSDETAIL|                  ; -> Word: &000166AC
        LDR     R3,[R3,#0]
|NEXTOBJECT2|
        LDR     R2,[R11,#ObjDrawState]
        CMP     R2,#ObjDrawStateDrawIfNear
        BNE     |ADVANCETONEXTOBJ2|

        LDR     R2,[R11,#ObjCullBackface]  ; =40
        CMP     R2,#0
        BEQ     |NOCULLBACKFACE2|

        LDR     R2,[R11,#ObjDist]
        CMP     R2,#ObjDistMax
        BLT     |ADVANCETONEXTOBJ2|

|NOCULLBACKFACE2|
        LDR     R4,[R11,#ObjMesh] ; Get object number
        CMP     R4,#MESH_FIELD_BOUNDARY                         ; ="L" (76)
        CMPEQ   R3,#9 ; graphics detail
        BEQ     |DRAWNOFIELD|

        STMFD   R13!,{R1,R3,R11}
        BL      |DRAWOBJECT|
        LDMFD   R13!,{R1,R3,R11}

|DRAWNOFIELD|
        MOV     R2,#ObjDrawStateDrawn
        STR     R2,[R11,#ObjDrawState]

|ADVANCETONEXTOBJ2|
        ADD     R11,R11,#BytesPerObj                    ; ="0" (48)
        SUBS    R1,R1,#1
        BPL     |NEXTOBJECT2|

|DRAWOBJECTLOOP|
        LDR     R0,|POBJARRAY2|                  ; -> Word: MemObjArray
        LDR     R1,|NUMOBJMINUS1|                  ; -> Word: &000001DE
        MOV     R12,#0 ; farthest object distance
        MOV     R11,#0 ; farthest object pointer
|FINDFARTHESTOBJLOOP|
        LDR     R2,[R0,#ObjDrawState]
        CMP     R2,#ObjDrawStateDrawIfNear
        BNE     |FINDFARTHESTNOTTOBEDRAWN|

        LDR     R2,[R0,#ObjDist]
        CMP     R2,R12
        MOVGE   R12,R2 ; new farthest object
        MOVGE   R11,R0

|FINDFARTHESTNOTTOBEDRAWN|
        ADD     R0,R0,#BytesPerObj                      ; ="0" (48)
        SUBS    R1,R1,#1
        BPL     |FINDFARTHESTOBJLOOP|

        CMP     R11,#0
        BEQ     |NOFARTHESTOBJ|

        MOV     R2,#ObjDrawStateDrawn
        STR     R2,[R11,#ObjDrawState]
        BL      |DRAWOBJECT|
        B       |DRAWOBJECTLOOP|                     ; Ends

|NOFARTHESTOBJ|
        LDR     R0,|POBJARRAY2|                  ; -> Word: MemObjArray
        LDR     R1,|NUMOBJMINUS1|                  ; -> Word: &000001DE

|SETOBJTODRAWLOOP|
        LDR     R2,[R0,#ObjDrawState]
        CMP     R2,#ObjDrawStateCull
        MOVNE   R2,#ObjDrawStateDrawIfNear
        STRNE   R2,[R0,#ObjDrawState]

        ADD     R0,R0,#BytesPerObj                      ; ="0" (48)
        SUBS    R1,R1,#1
        BPL     |SETOBJTODRAWLOOP|

        LDR     R0,|FIRSTOBJTOCALCVIS|                  ; -> Word: &00000000
        SUBS    R0,R0,#1
        MOVMI   R0,#CalcObjVisInterval
        STR     R0,|FIRSTOBJTOCALCVIS|                  ; -> Word: &00000000

        LDR     R0,|PSPLITSCREEN14|                  ; -> Word: &00016B28
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BNE     |NODETAILINSERIALGAME|

        LDR     R0,|PMISSIONNUM5|                  ; -> Word: &000177B8
        LDR     R0,[R0,#0] ; get mission number
        CMP     R0,#&0B                         ; =11
        CMPNE   R0,#&0C                         ; =12
        CMPNE   R0,#&1A                         ; =26
        CMPNE   R0,#MissionFirstRecon           ; ="e" (101)
        CMPNE   R0,#&1F                         ; =31
        BLEQ    |DOSNOW|

        LDR     R0,|PMISSIONNUM5|                  ; -> Word: &000177B8
        LDR     R0,[R0,#0]
        CMP     R0,#&0F                         ; =15
        CMPNE   R0,#&10                         ; =16
        CMPNE   R0,#&1C                         ; =28
        BLEQ    |DORAIN|

        BL      |DRAWGROUNDSPECKS|

|NODETAILINSERIALGAME|
        LDR     R0,|ANOTHERNUMOBJMINUS1|                  ; -> Word: &000001DE
        STR     R0,|NUMOBJMINUS1|                  ; -> Word: &000001DE

        LDR     R0,|P5PREVENTTIMESKIP|                  ; -> Word: &00015714
        MOV     R1,#0 ; nothing happened yet
        STR     R1,[R0,#0]

        LDR     R1,|INTERVALTIMERBLK|                  ; -> Word: &0001C824
        MOV     R0,#ReadIntervalTimer
        SWI     OS_Word

        LDR     R6,|PGRAPHICSDETAIL|                  ; -> Word: &000166AC
        LDR     R6,[R6,#0]

        LDR     R5,|PSPLITSCREEN14|                  ; -> Word: &00016B28
        LDR     R5,[R5,#0]
        CMP     R5,#1
        SUBEQ   R6,R6,#3 ; reduce detail if split screen

        LDRB    R5,|L0000B6B4.5_byte_Time|      ; -> 5 byte Time: &0000000000
        CMP     R5,R6
        BEQ     |L0000BC64|

        LDR     R4,|CLIPDIST|                  ; -> Word: &00000080
        ADDLT   R4,R4,#1
        SUBGT   R4,R4,#1

        ADD     R6,R6,R6,ASR #2
        CMP     R5,R6
        SUBGT   R4,R4,#&0F                      ; =15
        CMP     R4,#&32                         ; ="2" (50)
        MOVLT   R4,#&32                         ; ="2" (50)

        LDR     R5,|MAXCLIPDIST|                  ; -> Word: &00000200
        CMP     R4,R5
        MOVGT   R4,R5
        STR     R4,|CLIPDIST|                  ; -> Word: &00000080

        RSB     R4,R4,#&01,24 ; bug?                 ; =&100
        ADD     R4,R4,#&01,24 ; bug?                 ; =&100
        STR     R4,|UNUSEDCLIPDIST| ; bug?           ; -> Word: &00000000

|WAITFORTIMERLOOP2|
        LDR     R1,|INTERVALTIMERBLK|                  ; -> Word: &0001C824
        MOV     R0,#ReadIntervalTimer
        SWI     OS_Word

        ; If drawing took less than the expected time then wait
        LDRB    R5,|L0000B6B4.5_byte_Time|      ; -> 5 byte Time: &0000000000
        CMP     R5,#MinCentisecondsPerFrame
        BLT     |WAITFORTIMERLOOP2|

|L0000BC64|
        BL      |SERVICELIGHTNING|

        LDR     R14,|RETURNADDR9|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|INTERVALTIMERBLK|
        DCD     |L0000B6B4.5_byte_Time|
|PMISSIONNUM5|
        DCD     |MISSIONNUM|
|PSPLITSCREEN14|
        DCD     |SPLITSCREEN|

|ADJUSTCAMPOSFORSEA|
        ; The sea follows the player around
        CMP     R8,#0                           ; Function entry, (alters flags)
        MOVGT   R8,#0 ; x pos <= 0
        MOV     R10,#0 ; y pos == 0
        MOV     PC,R14                          ; Function exit, Ends

|DRAWOBJECT|
; R11 = object address
        STR     R14,|RETFROMDRAWOBJECT|                 ; -> Word: &00000000, Function entry, (alters flags)
        LDR     R0,|SRCCOORDSPLUS16|                  ; -> Word: (MemSrcCoords+&10)
        LDMIA   R11,{R1,R2,R4-R8} ; bug? R8 not needed
        ; R1 ObjMesh
        ; R2 ObjDrawState
        ; R4 ObjDist
        ; R5 ObjCoordX
        ; R6 ObjCoordY
        ; R7 ObjCoordZ

        STR     R4,|OBJDIST|                  ; -> Word: &00000000

        LDR     R12,[R11,#ObjCullBackface]     ; =40
        STR     R12,|CULLBACKFACE|                 ; -> Word: &00000000

        STR     R1,|OBJMESHNUMBERTODRAW|        ; -> Word: &00000000
        CMP     R1,#MESH_SEA       ; ="c" (99)
        LDR     R9,|OBJ3D2|                  ; -> Word: MemObj3DAddrArray
        ADD     R9,R9,R1,LSL #BytesPerAddressLog2
        LDR     R9,[R9,#0] ; get graphic data address

        LDR     R11,|CAMPOS2|                 ; -> Word: &0001C7F4
        LDMIA   R11,{R8,R10,R11}
        BLEQ    |ADJUSTCAMPOSFORSEA|

        SUB     R8,R8,R5 ; x pos
        SUB     R10,R10,R6 ; y pos
        SUB     R11,R11,R7 ; z pos

        STMFD   R13!,{R8,R10,R11}

        LDMIA   R9,{R1-R3,R5-R8,R14}
        ; R1 MeshSimplifyDist
        ; R2 MeshPrimCountMinus1
        ; R3 MeshVertCountMinus1
        ; R5 MeshSimplePrimCountMinus1
        ; R6 MeshSimpleVertCountMinus1
        ; R8 MeshClipDist
        ; R14 MeshPolygonStyle

        STR     R8,|CLIPY|                  ; -> Word: &00000000

        LDR     R8,|ALLOWOUTLINEORTHICK|                  ; -> Word: &00000000
        CMP     R8,#0
        MOVEQ   R14,#PolygonStyleNoOutline
        STR     R14,|POLYGONOUTLINESTYLE|                 ; -> Word: &00000000

        MOV     R7,R3,LSL #VertDataSizeALog2
        ADD     R7,R7,R3,LSL #VertDataSizeBLog2 ; MeshVertCountMinus1 times BytesPerVert
        ADD     R7,R7,#(BytesPerMeshHdr+BytesPerVert)
        ADD     R7,R7,R9 ; address of first primitive
        STR     R7,|VERTEXINDICES|                  ; -> Word: &00000000

        CMP     R1,R4 ; Check distance - use simple object mesh?
        MOVLT   R2,R5 ; MeshSimplePrimCountMinus1
        MOVLT   R3,R6 ; MeshSimpleVertCountMinus1

        ; Vertex data follows immediately after the mesh header
        ADD     R4,R9,#BytesPerMeshHdr            ; =" " (32)
        LDR     R14,|PROTATIONMATRIX|                 ; -> Word: &0001D31C

|MATRIXMULTIPLYLOOP3|
        LDMIA   R4,{R5,R6} ; get VertX,VertY

        LDMFD   R13,{R8,R9} ; get object x,y coordinates
        SUB     R5,R5,R8
        SUB     R6,R6,R9

        LDMIA   R14!,{R9-R12}
        MUL     R7,R5,R12
        MOV     R7,R7,ASR #12
        MUL     R8,R6,R11
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#0]

        MUL     R7,R6,R9
        MOV     R7,R7,ASR #12
        MUL     R8,R5,R10
        ADD     R5,R7,R8,ASR #12

        LDR     R6,[R4,#VertZ]
        LDR     R8,[R13,#8] ; get object z coordinate
        SUB     R6,R6,R8

        LDMIA   R14!,{R9-R12}
        MUL     R7,R5,R12
        MOV     R7,R7,ASR #12
        MUL     R8,R6,R11
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#4]

        MUL     R7,R6,R9
        MOV     R7,R7,ASR #12
        MUL     R8,R5,R10
        ADD     R6,R7,R8,ASR #12

        LDR     R5,[R0,#0]

        LDMIA   R14,{R9-R12}
        MUL     R7,R6,R9
        MOV     R7,R7,ASR #12
        MUL     R8,R5,R10
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#8]

        MUL     R7,R5,R12
        MOV     R7,R7,ASR #12
        MUL     R8,R6,R11
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#0]

        SUB     R14,R14,#&20                    ; =" " (32)
        ADD     R0,R0,#&10                      ; =16
        ADD     R4,R4,#BytesPerVert                      ; =12

        SUBS    R3,R3,#1
        BPL     |MATRIXMULTIPLYLOOP3|

        LDR     R4,|VERTEXINDICES|                  ; -> Word: &00000000
        ADD     R13,R13,#&0C                    ; =12
        CMP     R2,#MeshPrimCountMinus1DrawPoint
        BEQ     |DRAW1STCOORDASPIXEL|

        MOV     R0,R4
        MOV     R1,R2
        CMP     R1,#0
        LDRLT   R14,|RETFROMDRAWOBJECT|                 ; -> Word: &00000000
        MOVLT   PC,R14                          ; Function exit if LT

        LDR     R9,|OBJDIST| ; bug? unused         ; -> Word: &00000000
        CMP     R9,#&03,24  ; bug? unused          ; =&300
|DRAWPOLYGONLOOP2|
        ; R0 = vertex indices for next polygon
        ; R1 = no. of polygons left to draw -1
        LDMIA   R0!,{R9-R12} ; get vertex indices, colour and z simplification dist
        STMFD   R13!,{R0,R1}
        LDR     R2,|OBJDIST|                  ; -> Word: &00000000
        CMP     R12,R2
        MOVLT   R9,R9,LSL #16
        MOVLT   R9,R9,LSR #16 ; terminate after second index
        MOV     R11,R11,LSL #24
        MOV     R11,R11,LSR #24 ; extract colour
        STR     R11,|POLYGONCOLOUR|                 ; -> Word: &00000000
        MOV     R8,#0
        LDR     R11,|LINECOORDS5|                 ; -> Word: MemLineCoords
        LDR     R12,|SRCCOORDS|                 ; -> Word: MemSrcCoords
        LDR     R14,|CLIPY|                 ; -> Word: &00000000

        MOV     R2,R9,LSL #24
        MOV     R2,R2,LSR #24 ; 1st vertex index
        ADD     R2,R12,R2,LSL #4
        LDMIA   R2,{R0-R2} ; get 1st vertex coordinates
        CMP     R1,R14
        ADDLT   R8,R8,#1
        STMIA   R11!,{R0-R2}

        MOV     R2,R9,LSL #16
        MOV     R2,R2,LSR #24 ; 2nd vertex index
        ADD     R2,R12,R2,LSL #4
        LDMIA   R2,{R0-R2} ; get 2nd vertex coordinates
        CMP     R1,R14
        ADDLT   R8,R8,#1
        STMIA   R11!,{R0-R2}

        MOV     R2,R9,LSL #8
        MOV     R2,R2,LSR #24 ; 3rd vertex index
        CMP     R2,#VertexThinWhiteLine8Dash                         ; ="" (253)
        BLGE    |DRAWSPECIALLINE|
        CMP     R2,#VertexEnd
        MOVEQ   R12,#2
        BEQ     |ENDOFPOLYGON|

        ADD     R2,R12,R2,LSL #4
        LDMIA   R2,{R0-R2} ; get 3rd vertex coordinates
        CMP     R1,R14
        ADDLT   R8,R8,#1
        STMIA   R11!,{R0-R2}

        MOV     R2,R9,LSR #24 ; 4th vertex index
        CMP     R2,#VertexEnd
        MOVEQ   R12,#3
        BEQ     |ENDOFPOLYGON|
        CMP     R2,#Vertex32OrangePoints
        BLGE    |DRAWSPECIALTRIANGLE|

        ADD     R2,R12,R2,LSL #4
        LDMIA   R2,{R0-R2} ; get 4th vertex coordinates
        CMP     R1,R14
        ADDLT   R8,R8,#1
        STMIA   R11!,{R0-R2}

        MOV     R2,R10,LSL #24
        MOV     R2,R2,LSR #24 ; 5th vertex index
        CMP     R2,#VertexEnd
        MOVEQ   R12,#4
        BEQ     |ENDOFPOLYGON|
        ADD     R2,R12,R2,LSL #4
        LDMIA   R2,{R0-R2} ; get 5th vertex coordinates
        CMP     R1,R14
        ADDLT   R8,R8,#1
        STMIA   R11!,{R0-R2}

        MOV     R2,R10,LSL #16
        MOV     R2,R2,LSR #24 ; 6th vertex index
        CMP     R2,#VertexEnd
        MOVEQ   R12,#5
        BEQ     |ENDOFPOLYGON|
        ADD     R2,R12,R2,LSL #4
        LDMIA   R2,{R0-R2} ; get 6th vertex coordinates
        CMP     R1,R14
        ADDLT   R8,R8,#1
        STMIA   R11!,{R0-R2}

        MOV     R2,R10,LSL #8
        MOV     R2,R2,LSR #24 ; 7th vertex index
        CMP     R2,#VertexEnd
        MOVEQ   R12,#6
        BEQ     |ENDOFPOLYGON|
        ADD     R2,R12,R2,LSL #4
        LDMIA   R2,{R0-R2} ; get 7th vertex coordinates
        CMP     R1,R14
        ADDLT   R8,R8,#1
        STMIA   R11!,{R0-R2}

        MOV     R2,R10,LSR #24 ; 8th vertex index
        CMP     R2,#VertexEnd
        MOVEQ   R12,#7
        BEQ     |ENDOFPOLYGON|
        ADD     R2,R12,R2,LSL #4
        LDMIA   R2,{R0-R2} ; get 8th vertex coordinates
        CMP     R1,R14
        ADDLT   R8,R8,#1
        STMIA   R11!,{R0-R2}

        MOV     R12,#8
|ENDOFPOLYGON|
        ; R12 = no. of vertices in polygon
        ; R8 = no. of clipped vertices in polygon
        CMP     R12,#2
        BEQ     |POLYGONISALINE|

        CMP     R8,#0
        BLGT    |CLIPPOLYGON|

        LDR     R10,|LINECOORDS5|                 ; -> Word: MemLineCoords
        LDR     R11,|LINECOORDS2|                 ; -> Word: &0002FDC0
        LDR     R8,|DIVDATA2|                  ; -> Word: &00077338

count SETA 0
        WHILE count < 3

        LDMIA   R10!,{R0-R2}
        BL      |PROJECT3DB|
        STMIA   R11!,{R0,R2}

count SETA count + 1
        WEND

        LDR     R9,|CULLBACKFACE|                  ; -> Word: &00000000
        CMP     R9,#1
        BNE     |NOCULLBACKFACE|

        ; Looks like a cross product
        SUB     R9,R11,#&18                     ; =24
        LDMIA   R9,{R0-R5}
        SUB     R6,R2,R0 ; x1-x0
        SUB     R7,R3,R1 ; y1-y0
        SUB     R8,R4,R2 ; x2-x1
        SUB     R9,R5,R3 ; y2-y1
        MUL     R0,R6,R9 ; (x1-x0) * (y2-y1)
        MUL     R1,R8,R7 ; (x2-x1) * (y1-y0)
        SUB     R0,R0,R1 ; ((x1-x0) * (y2-y1)) - ((x2-x1) * (y1-y0))
        CMP     R0,#0
        BLT     |DRAWNEXTPOLYGON| ; polygon is back-facing

|NOCULLBACKFACE|
        SUBS    R9,R12,#4
        BMI     |ENDOFPOLYGON2|

        LDR     R8,|DIVDATA2|                  ; -> Word: &00077338

count SETA 0
        WHILE count < 5

        LDMIA   R10!,{R0-R2}
        BL      |PROJECT3DB|
        STMIA   R11!,{R0,R2}

        SUBS    R9,R9,#1
        BMI     |ENDOFPOLYGON2|

count SETA count + 1
        WEND

|ENDOFPOLYGON2|
        LDR     R0,|LINECOORDS2|                  ; -> Word: &0002FDC0
        LDR     R1,|POLYGONCOLOUR|                  ; -> Word: &00000000
        LDR     R2,|POLYGONOUTLINESTYLE|                  ; -> Word: &00000000
        MOV     R3,#DrawPolygonMayDarken
        BL      |DRAWPOLYGON|
|DRAWNEXTPOLYGON|
        LDMFD   R13!,{R0,R1}
        SUBS    R1,R1,#1
        BPL     |DRAWPOLYGONLOOP2|

        LDR     R14,|RETFROMDRAWOBJECT|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|CLIPY|
        DCD     &00000000                       ; Word r/w (referenced)
|CULLBACKFACE|
        DCD     &00000000                       ; Word r/w (referenced)
|POLYGONOUTLINESTYLE|
        DCD     &00000000                       ; Word r/w (referenced)
|ALLOWOUTLINEORTHICK|
        DCD     &00000000                       ; Word r/- (referenced)
|DIVDATA2|
        DCD     &00077338                       ; Word r/- (referenced)

|POLYGONISALINE|
        ; R8 = no. of clipped vertices in polygon
        CMP     R8,#0
        BGT     |CLIPPOLYGONISALINE|

        LDR     R10,|LINECOORDS5|                 ; -> Word: MemLineCoords
        LDMIA   R10!,{R0-R2}
        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        STMDB   R13,{R0,R2}

        LDMIA   R10!,{R0-R2}
        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        MOV     R1,R2

        LDMDB   R13,{R2,R3}
        LDR     R5,|OBJDIST|                  ; -> Word: &00000000
        CMP     R5,#MaxThickLineDist          ; =&40000
        BGT     |NODRAWTHICK|

        LDR     R5,|POLYGONOUTLINESTYLE|                  ; -> Word: &00000000
        CMP     R5,#PolygonStyleNoOutline
        BEQ     |NODRAWTHICK|

        LDR     R4,|POLYGONCOLOUR|                  ; -> Word: &00000000
        BL      |DRAWTHICK| ; In R0-R3 coords, R4 colour
        B       |DRAWNEXTPOLYGON|                     ; Ends

|CLIPPOLYGONISALINE|
        ; R8 = no. of clipped vertices in polygon
        CMP     R8,#2
        BEQ     |DRAWNEXTPOLYGON|

        LDR     R10,|LINECOORDS5|                 ; -> Word: MemLineCoords
        LDMIA   R10,{R0-R5}
        CMP     R1,R4
        BGT     |L0000C0E8| ; y0 > clip dist

        BL      |CLIPLINESTART|
        B       |L0000C0EC|                     ; Ends

|L0000C0E8|
        BL      |CLIPLINEEND|

|L0000C0EC|
        LDR     R10,|LINECOORDS5|                 ; -> Word: MemLineCoords
        STMIA   R10,{R0-R5}

        ADD     R10,R10,#&0C                    ; =12
        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        STMDB   R13,{R0,R2}

        LDMIA   R10!,{R0-R2}
        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        MOV     R1,R2

        LDMDB   R13,{R2,R3}
        LDR     R5,|OBJDIST|                  ; -> Word: &00000000
        CMP     R5,#MaxThickLineDist          ; =&40000
        BGT     |NODRAWTHICK|

        LDR     R5,|POLYGONOUTLINESTYLE|                  ; -> Word: &00000000
        CMP     R5,#PolygonStyleNoOutline
        BEQ     |NODRAWTHICK|

        LDR     R4,|POLYGONCOLOUR|                  ; -> Word: &00000000
        BL      |DRAWTHICK| ; In R0-R3 coords, R4 colour
        B       |DRAWNEXTPOLYGON|                     ; Ends

|NODRAWTHICK|
        LDR     R4,|POLYGONCOLOUR|                  ; -> Word: &00000000
        BL      |DRAWLINE|
        B       |DRAWNEXTPOLYGON|                     ; Ends

|COSINE9|
        DCD     MemCosine                       ; Word r/- (referenced)
|SINE9|
        DCD     MemSine                       ; Word r/- (referenced)

|MAKEROTATIONMATRIX|
        ADR     R12,|ROTATIONMATRIX|                 ; -> Word array: &00000000, Function entry, (alters flags)
        LDR     R0,|COSINE9|                  ; -> Word: MemCosine
        LDR     R1,|SINE9|                  ; -> Word: MemSine

        LDR     R2,|XANGLE|                  ; -> Word array: &00000000
        LDR     R4,[R0,R2]
        LDR     R6,[R1,R2]
        ADD     R2,R2,#QuarterTurn                   ; =&5A0
        LDR     R5,[R0,R2]
        LDR     R7,[R1,R2]
        STMIA   R12!,{R4-R7}

        LDR     R2,|YANGLE|                  ; -> Word array: &00000000
        LDR     R4,[R0,R2]
        LDR     R6,[R1,R2]
        ADD     R2,R2,#QuarterTurn                   ; =&5A0
        LDR     R5,[R0,R2]
        LDR     R7,[R1,R2]
        STMIA   R12!,{R4-R7}

        LDR     R2,|ZANGLE|                  ; -> Word array: &00000000
        LDR     R4,[R0,R2]
        LDR     R6,[R1,R2]
        ADD     R2,R2,#QuarterTurn                   ; =&5A0
        LDR     R5,[R0,R2]
        LDR     R7,[R1,R2]
        STMIA   R12!,{R4-R7}

        MOV     PC,R14                          ; Function exit, Ends

|ROTATIONMATRIX|
        DCD     &00000000                       ; Word array -/w (referenced)
        DCD     &00000000                       ;~~~ Word array -/w
        DCD     &00000000                       ;~~~ Word array -/w
        DCD     &00000000                       ;~~~ Word array -/w
|ROTATIONMATRIXB|
        DCD     &00000000                       ;~~~ Word array -/w
        DCD     &00000000                       ;~~~ Word array -/w
        DCD     &00000000                       ;~~~ Word array -/w
        DCD     &00000000                       ;~~~ Word array -/w
|ROTATIONMATRIXC|
        DCD     &00000000                       ;~~~ Word array -/w
        DCD     &00000000                       ;~~~ Word array -/w
        DCD     &00000000                       ;~~~ Word array -/w
        DCD     &00000000                       ;~~~ Word array -/w
|XANGLE|
        DCD     &00000000                       ;~~~ Word array r/- (referenced)
|YANGLE|
        DCD     &00000000                       ;~~~ Word array r/- (referenced)
|ZANGLE|
        DCD     &00000000                       ;~~~ Word array r/- (referenced)
|GANG|
        DCD     &0003E8C8                       ;~~~ Word array r/- (referenced)
|P2GRAPHICSDETAIL|
        DCD     |GRAPHICSDETAIL|
|L0000C1F0|
        DCD     &00000000                       ;~~~ Word array r/w (referenced)
|P6PREVENTTIMESKIP|
        DCD     |PREVENTTIMESKIP|

|DRAWGROUNDSPECKS|
        STR     R14,|RETFROMDRAWOBJECT|                 ; -> Word: &00000000, Function entry, (alters flags)

        LDR     R0,|CAMERAPOSZ|                  ; -> Word array: &00000000
        CMN     R0,#MaxHeightDrawGroundSpecks    ; =&2800
        BLT     |NOGROUNDSPECKS|

        RSB     R0,R0,#0
        STR     R0,|L0000C1F0|                  ; -> Word array: &00000000

        LDR     R0,|P6PREVENTTIMESKIP|                  ; -> Word array: &00015714
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BNE     |NOMOVESPECKS|

        LDR     R11,|OLDCAMPOS|                 ; -> Word: &0001D9D4
        LDMIA   R11,{R11,R12}
        CMP     R11,#0
        LDR     R8,|CAMPOS|                  ; -> Word: &0001C7F4
        LDMIA   R8,{R8,R9}
        SUB     R11,R8,R11
        SUB     R12,R9,R12
        MOVEQ   R11,#0
        MOVEQ   R12,#0
        LDR     R0,|GANG|                  ; -> Word array: &0003E8C8

        LDR     R1,|P2GRAPHICSDETAIL|                  ; -> Word array: &000166AC
        LDR     R1,[R1,#0]

        CMP     R1,#6
        MOVEQ   R1,#&7F                         ; =127

|MOVEGROUNDSPECKLOOP|
        LDMIA   R0,{R2,R3}
        SUB     R2,R2,R11,LSL #10
        SUB     R3,R3,R12,LSL #10
        CMP     R2,#&0A,12                      ; =&A00000
        SUBGT   R2,R2,#&05,10                   ; =&1400000
        CMP     R3,#&0A,12                      ; =&A00000
        SUBGT   R3,R3,#&05,10                   ; =&1400000
        CMN     R2,#&0A,12                      ; =&A00000
        ADDLT   R2,R2,#&05,10                   ; =&1400000
        CMN     R3,#&0A,12                      ; =&A00000
        ADDLT   R3,R3,#&05,10                   ; =&1400000
        STMIA   R0!,{R2,R3}
        SUBS    R1,R1,#1
        BPL     |MOVEGROUNDSPECKLOOP|

|NOMOVESPECKS|
        LDR     R4,|GANG|                  ; -> Word array: &0003E8C8

        LDR     R3,|P2GRAPHICSDETAIL|                  ; -> Word array: &000166AC
        LDR     R3,[R3,#0]

        LDR     R0,|SRCCOORDSPLUS16|                  ; -> Word: (MemSrcCoords+&10)
        CMP     R3,#6
        MOVEQ   R3,#&7F                         ; =127
        LDR     R14,|PROTATIONMATRIX|                 ; -> Word: &0001D31C
|DRAWGROUNDSPECKLOOP|
        LDMIA   R4!,{R5,R6}
        MOV     R5,R5,ASR #AngleShift
        MOV     R6,R6,ASR #AngleShift
        LDMIA   R14!,{R9-R12}
        MUL     R7,R5,R12
        MOV     R7,R7,ASR #12
        MUL     R8,R6,R11
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#0]
        MUL     R7,R6,R9
        MOV     R7,R7,ASR #12
        MUL     R8,R5,R10
        ADD     R5,R7,R8,ASR #12
        LDR     R6,|L0000C1F0|                  ; -> Word array: &00000000
        LDMIA   R14!,{R9-R12}
        MUL     R7,R5,R12
        MOV     R7,R7,ASR #12
        MUL     R8,R6,R11
        ADD     R8,R7,R8,ASR #12
        CMP     R8,#&1E                         ; =30
        BLT     |DRAWNEXTGROUNDSPECK|

        STR     R8,[R0,#4]

        MUL     R7,R6,R9
        MOV     R7,R7,ASR #12
        MUL     R8,R5,R10
        ADD     R6,R7,R8,ASR #12
        LDR     R5,[R0,#0]
        LDMIA   R14,{R9-R12}
        MUL     R7,R6,R9
        MOV     R7,R7,ASR #12
        MUL     R8,R5,R10
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#8]
        MUL     R7,R5,R12
        MOV     R7,R7,ASR #12
        MUL     R8,R6,R11
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#0]
        STMFD   R13!,{R0,R3,R4,R14}
        LDR     R0,|SRCCOORDSPLUS16|                  ; -> Word: (MemSrcCoords+&10)
        LDMIA   R0,{R0-R2}
        BL      |PROJECT3D| ; In R0-R2, out R0,R2

        LDR     R10,|MAXCOORDX|                 ; -> Word: &0000013F
        ADD     R0,R0,R10,LSL #(CoordToScreenLog2-1)
        MOV     R0,R0,ASR #CoordToScreenLog2
        CMP     R0,#0
        BLT     |NOGROUNDSPECK|

        CMP     R0,R10
        BGE     |NOGROUNDSPECK|

        LDR     R10,|MAXCOORDY|                 ; -> Word: &000000F2
        ADD     R2,R2,R10,LSL #(CoordToScreenLog2-1)
        MOV     R2,R2,ASR #CoordToScreenLog2
        CMP     R2,#1
        BLT     |NOGROUNDSPECK|

        CMP     R2,R10
        BGT     |NOGROUNDSPECK|

        LDR     R10,|FRAMEBUFFER98|                 ; -> Word: &00000000
        ADD     R10,R10,R0
        MOV     R3,R2,LSL #RowStrideALog2
        ADD     R3,R3,R2,LSL #RowStrideBLog2
        ADD     R10,R10,R3

        LDRB    R8,[R10,#0]
        CMP     R8,#Olive
        MOVEQ   R9,#Honey
        MOVNE   R9,#Black
        CMP     R8,#RoyalAzure
        MOVEQ   R9,#White
        CMP     R8,#OffWhite                         ; ="" (253)
        MOVEQ   R9,#MediumGrey
        CMP     R9,#Black
        STRNEB  R9,[R10,#0]

|NOGROUNDSPECK|
        LDMFD   R13!,{R0,R3,R4,R14}
|DRAWNEXTGROUNDSPECK|
        SUB     R14,R14,#&20                    ; =" " (32)
        SUBS    R3,R3,#1
        BPL     |DRAWGROUNDSPECKLOOP|

|NOGROUNDSPECKS|
        LDR     R0,|CAMPOS|                  ; -> Word: &0001C7F4
        LDMIA   R0,{R0-R2}
        LDR     R3,|OLDCAMPOS|                  ; -> Word: &0001D9D4
        STMIA   R3,{R0-R2}

        LDR     R14,|RETFROMDRAWOBJECT|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|SNOW|
        DCD     &0003E0CC                       ; Word r/- (referenced)
|P3GRAPHICSDETAIL|
        DCD     |GRAPHICSDETAIL|
|NEGCAMERAPOSZ|
        DCD     &00000000                       ; Word r/w (referenced)
|P7PREVENTTIMESKIP|
        DCD     |PREVENTTIMESKIP|

|DOSNOW|
        STR     R14,|RETFROMDRAWOBJECT|                 ; -> Word: &00000000, Function entry, (alters flags)

        LDR     R0,|CAMERAPOSZ|                  ; -> Word array: &00000000
        CMN     R0,#MaxHeightDrawSnow    ; =&2800
        BLT     |RETFROMSNOW|

        RSB     R0,R0,#0
        STR     R0,|NEGCAMERAPOSZ|                  ; -> Word: &00000000

        LDR     R0,|P7PREVENTTIMESKIP|                  ; -> Word: &00015714
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BNE     |NOMOVESNOW|

        LDR     R11,|OLDCAMPOS|                 ; -> Word: &0001D9D4
        LDMIA   R11,{R10-R12}
        CMP     R10,#0
        LDR     R8,|CAMPOS|                  ; -> Word: &0001C7F4
        LDMIA   R8,{R7-R9}

        SUB     R10,R7,R10
        SUB     R11,R8,R11
        SUB     R12,R9,R12

        MOVEQ   R10,#0
        MOVEQ   R11,#0
        MOVEQ   R12,#0

        LDR     R0,|SNOW|                  ; -> Word: &0003E0CC
        MOV     R1,#&A0                         ; ="" (160)
|MOVESNOWLOOP|
        LDMIA   R0,{R2-R4}

        SUB     R2,R2,R10,LSL #10
        SUB     R3,R3,R11,LSL #10
        SUB     R4,R4,R12,LSL #10

        CMP     R2,#&05,14                      ; =&140000
        SUBGT   R2,R2,#&0A,14                   ; =&280000

        CMP     R3,#&05,14                      ; =&140000
        SUBGT   R3,R3,#&0A,14                   ; =&280000

        CMN     R2,#&05,14                      ; =&140000
        ADDLT   R2,R2,#&0A,14                   ; =&280000

        CMN     R3,#&05,14                      ; =&140000
        ADDLT   R3,R3,#&0A,14                   ; =&280000

        ADD     R4,R4,#&01,18                   ; =&4000

        TST     R1,#1
        ADDNE   R4,R4,#&01,18                   ; =&4000

        CMP     R4,#&05,14                      ; =&140000
        SUBGT   R4,R4,#&0A,14                   ; =&280000

        CMN     R4,#&05,14                      ; =&140000
        ADDLT   R4,R4,#&0A,14                   ; =&280000

        STMIA   R0!,{R2-R4}
        SUBS    R1,R1,#1
        BPL     |MOVESNOWLOOP|

|NOMOVESNOW|
        LDR     R4,|SNOW|                  ; -> Word: &0003E0CC

        LDR     R3,|P3GRAPHICSDETAIL|                  ; -> Word: &000166AC
        LDR     R3,[R3,#0]

        LDR     R0,|SRCCOORDSPLUS16|                  ; -> Word: (MemSrcCoords+&10)
        LDR     R14,|PROTATIONMATRIX|                 ; -> Word: &0001D31C
        MOV     R3,R3,LSL #2
        MOV     R3,#&A0                         ; ="" (160)
|DRAWSNOWLOOP|
        LDMIA   R4!,{R5,R6}
        MOV     R5,R5,ASR #AngleShift
        MOV     R6,R6,ASR #AngleShift

        LDMIA   R14!,{R9-R12}
        MUL     R7,R5,R12
        MOV     R7,R7,ASR #12
        MUL     R8,R6,R11
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#0]
        MUL     R7,R6,R9
        MOV     R7,R7,ASR #12
        MUL     R8,R5,R10
        ADD     R5,R7,R8,ASR #12

        LDR     R9,|NEGCAMERAPOSZ|                  ; -> Word: &00000000
        LDMIA   R4!,{R6}
        MOV     R6,R6,ASR #AngleShift
        CMP     R6,R9
        MOVGT   R6,R9

        LDMIA   R14!,{R9-R12}
        MUL     R7,R5,R12
        MOV     R7,R7,ASR #12
        MUL     R8,R6,R11
        ADD     R8,R7,R8,ASR #12
        CMP     R8,#&1E                         ; =30
        BLT     |NEXTSNOWFLAKE2|

        STR     R8,[R0,#4]

        MUL     R7,R6,R9
        MOV     R7,R7,ASR #12
        MUL     R8,R5,R10
        ADD     R6,R7,R8,ASR #12
        LDR     R5,[R0,#0]
        LDMIA   R14,{R9-R12}

        MUL     R7,R6,R9
        MOV     R7,R7,ASR #12
        MUL     R8,R5,R10
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#8]

        MUL     R7,R5,R12
        MOV     R7,R7,ASR #12
        MUL     R8,R6,R11
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#0]

        STMFD   R13!,{R0,R3,R4,R14}
        LDR     R0,|SRCCOORDSPLUS16|                  ; -> Word: (MemSrcCoords+&10)
        LDMIA   R0,{R0-R2}
        BL      |PROJECT3D| ; In R0-R2, out R0,R2

        LDR     R10,|MAXCOORDX|                 ; -> Word: &0000013F
        ADD     R0,R0,R10,LSL #(CoordToScreenLog2-1)
        MOV     R0,R0,ASR #CoordToScreenLog2
        CMP     R0,#4
        BLT     |NEXTSNOWFLAKE|

        SUB     R10,R10,#4
        CMP     R0,R10
        BGE     |NEXTSNOWFLAKE|

        LDR     R10,|MAXCOORDY|                 ; -> Word: &000000F2
        ADD     R2,R2,R10,LSL #(CoordToScreenLog2-1)
        MOV     R2,R2,ASR #CoordToScreenLog2
        CMP     R2,#4
        BLT     |NEXTSNOWFLAKE|

        SUB     R10,R10,#4
        CMP     R2,#&EC                         ; ="" (236)
        BGT     |NEXTSNOWFLAKE|

        LDR     R10,|FRAMEBUFFER98|                 ; -> Word: &00000000
        ADD     R10,R10,R0 ; +x
        MOV     R3,R2,LSL #RowStrideALog2
        ADD     R3,R3,R2,LSL #RowStrideBLog2 ; +(y * 320)
        ADD     R10,R10,R3

        LDR     R0,|SRCCOORDSPLUS16|                  ; -> Word: (MemSrcCoords+&10)
        LDR     R0,[R0,#4]

        MOV     R9,#White                         ; ="" (255)
        STRB    R9,[R10,#0]
        STRB    R9,[R10,#1]
        STRB    R9,[R10,#-1]
        STRB    R9,[R10,#-RowStride]                 ; =&3FFFFFB<<6
        STRB    R9,[R10,#RowStride]                  ; =5<<6

        CMP     R0,#320
        STRLTB  R9,[R10,#&3C3]                  ; =963
        STRLTB  R9,[R10,#&3BC]                  ; =956
        STRLTB  R9,[R10,#-&3B8]                 ; =-952
        STRLTB  R9,[R10,#-&3C1]                 ; =-961

        CMP     R0,#&0A,26                      ; =&280
        STRLTB  R9,[R10,#&282]                  ; =642
        STRLTB  R9,[R10,#&27F]                  ; =639
        STRLTB  R9,[R10,#-&27E]                 ; =-638

        CMP     R0,#&0F,26                      ; =&3C0
        STRLTB  R9,[R10,#&142]                  ; =322
        STRLTB  R9,[R10,#-(RowStride-1)]                 ; =-319

|NEXTSNOWFLAKE|
        LDMFD   R13!,{R0,R3,R4,R14}
|NEXTSNOWFLAKE2|
        SUB     R14,R14,#&20                    ; =" " (32)
        SUBS    R3,R3,#1
        BPL     |DRAWSNOWLOOP|

|RETFROMSNOW|
        LDR     R14,|RETFROMDRAWOBJECT|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|DORAIN|
        STR     R14,|RETFROMDRAWOBJECT|                 ; -> Word: &00000000, Function entry, (alters flags)

        LDR     R0,|CAMERAPOSZ|                  ; -> Word array: &00000000
        CMN     R0,#MaxHeightDrawRain    ; =&2800
        BLT     |RETFROMRAIN|

        RSB     R0,R0,#0
        STR     R0,|NEGCAMERAPOSZ|                  ; -> Word: &00000000

        LDR     R0,|P7PREVENTTIMESKIP|                  ; -> Word: &00015714
        LDR     R0,[R0,#0]
        CMP     R0,#0
        BNE     |NOMOVERAIN|

        LDR     R11,|OLDCAMPOS|                 ; -> Word: &0001D9D4
        LDMIA   R11,{R10-R12}
        CMP     R10,#0
        LDR     R8,|CAMPOS|                  ; -> Word: &0001C7F4
        LDMIA   R8,{R7-R9}

        SUB     R10,R7,R10
        SUB     R11,R8,R11
        SUB     R12,R9,R12

        MOVEQ   R10,#0
        MOVEQ   R11,#0
        MOVEQ   R12,#0

        LDR     R0,|SNOW|                  ; -> Word: &0003E0CC
        MOV     R1,#&A0                         ; ="" (160)
|MOVERAINLOOP|
        LDMIA   R0,{R2-R4}

        SUB     R2,R2,R10,LSL #10
        SUB     R3,R3,R11,LSL #10
        SUB     R4,R4,R12,LSL #10

        CMP     R2,#&05,14                      ; =&140000
        SUBGT   R2,R2,#&0A,14                   ; =&280000

        CMP     R3,#&05,14                      ; =&140000
        SUBGT   R3,R3,#&0A,14                   ; =&280000

        CMN     R2,#&05,14                      ; =&140000
        ADDLT   R2,R2,#&0A,14                   ; =&280000

        CMN     R3,#&05,14                      ; =&140000
        ADDLT   R3,R3,#&0A,14                   ; =&280000

        ADD     R4,R4,#&02,18                   ; =&8000
        TST     R1,#1
        ADDNE   R4,R4,#&02,18                   ; =&8000

        CMP     R4,#&05,14                      ; =&140000
        SUBGT   R4,R4,#&0A,14                   ; =&280000

        CMN     R4,#&05,14                      ; =&140000
        ADDLT   R4,R4,#&0A,14                   ; =&280000

        STMIA   R0!,{R2-R4}
        SUBS    R1,R1,#1
        BPL     |MOVERAINLOOP|

|NOMOVERAIN|
        LDR     R4,|SNOW|                  ; -> Word: &0003E0CC

        LDR     R3,|P3GRAPHICSDETAIL|                  ; -> Word: &000166AC
        LDR     R3,[R3,#0]

        LDR     R0,|SRCCOORDSPLUS16|                  ; -> Word: (MemSrcCoords+&10)
        LDR     R14,|PROTATIONMATRIX|                 ; -> Word: &0001D31C
        MOV     R3,R3,LSL #2
        MOV     R3,#&A0                         ; ="" (160)
|DRAWRAINLOOP|
        LDMIA   R4!,{R5,R6}
        MOV     R5,R5,ASR #AngleShift
        MOV     R6,R6,ASR #AngleShift

        LDMIA   R14!,{R9-R12}
        MUL     R7,R5,R12
        MOV     R7,R7,ASR #12
        MUL     R8,R6,R11
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#0]
        MUL     R7,R6,R9
        MOV     R7,R7,ASR #12
        MUL     R8,R5,R10
        ADD     R5,R7,R8,ASR #12

        LDR     R9,|NEGCAMERAPOSZ|                  ; -> Word: &00000000
        LDMIA   R4!,{R6}
        MOV     R6,R6,ASR #AngleShift
        CMP     R6,R9
        MOVGT   R6,R9

        LDMIA   R14!,{R9-R12}
        MUL     R7,R5,R12
        MOV     R7,R7,ASR #12
        MUL     R8,R6,R11
        ADD     R8,R7,R8,ASR #12
        CMP     R8,#&1E                         ; =30
        BLT     |NEXTRAINDROP2|

        STR     R8,[R0,#4]

        MUL     R7,R6,R9
        MOV     R7,R7,ASR #12
        MUL     R8,R5,R10
        ADD     R6,R7,R8,ASR #12
        LDR     R5,[R0,#0]
        LDMIA   R14,{R9-R12}
        MUL     R7,R6,R9
        MOV     R7,R7,ASR #12
        MUL     R8,R5,R10
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#8]
        MUL     R7,R5,R12
        MOV     R7,R7,ASR #12
        MUL     R8,R6,R11
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#0]
        STMFD   R13!,{R0,R3,R4,R14}
        LDR     R0,|SRCCOORDSPLUS16|                  ; -> Word: (MemSrcCoords+&10)
        LDMIA   R0,{R0-R2}
        BL      |PROJECT3D| ; In R0-R2, out R0,R2

        LDR     R10,|MAXCOORDX|                 ; -> Word: &0000013F
        ADD     R0,R0,R10,LSL #(CoordToScreenLog2-1)
        MOV     R0,R0,ASR #CoordToScreenLog2
        CMP     R0,#4
        BLT     |NEXTRAINDROP|

        SUB     R10,R10,#4
        CMP     R0,R10
        BGE     |NEXTRAINDROP|

        LDR     R10,|MAXCOORDY|                 ; -> Word: &000000F2
        ADD     R2,R2,R10,LSL #(CoordToScreenLog2-1)
        MOV     R2,R2,ASR #CoordToScreenLog2
        CMP     R2,#4
        BLT     |NEXTRAINDROP|

        SUB     R10,R10,#2
        CMP     R2,R10
        BGT     |NEXTRAINDROP|

        LDR     R10,|FRAMEBUFFER98|                 ; -> Word: &00000000
        ADD     R10,R10,R0
        MOV     R3,R2,LSL #RowStrideALog2
        ADD     R3,R3,R2,LSL #RowStrideBLog2
        ADD     R10,R10,R3
        LDR     R0,|SRCCOORDSPLUS16|                  ; -> Word: (MemSrcCoords+&10)
        LDR     R0,[R0,#4]

        MOV     R9,#DarkNavy
        STRB    R9,[R10,#0]

        CMP     R0,#&0A,26                      ; =&280
        STRLTB  R9,[R10,#1]
        STRLTB  R9,[R10,#-1]
        STRLTB  R9,[R10,#-RowStride]                 ; =&3FFFFFB<<6
        STRLTB  R9,[R10,#RowStride]                  ; =5<<6

|NEXTRAINDROP|
        LDMFD   R13!,{R0,R3,R4,R14}
|NEXTRAINDROP2|
        SUB     R14,R14,#&20                    ; =" " (32)
        SUBS    R3,R3,#1
        BPL     |DRAWRAINLOOP|

|RETFROMRAIN|
        LDR     R14,|RETFROMDRAWOBJECT|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|VERTEXINDICES|
        DCD     &00000000                       ; Word r/w (referenced)
|OLDCAMPOS|
        DCD     |L0000C864|
|L0000C864|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
|CAMPOS|
        DCD     |CAMERAPOSX|
|RETURNFROMCLIPPOLYGON|
        DCD     &00000000                       ; Word r/w (referenced)
|POLYGONCOLOUR|
        DCD     &00000000                       ; Word r/w (referenced)
|OBJMESHNUMBERTODRAW|
        DCD     &00000000                       ; Word -/w (referenced)
        DCD     &00000000                       ;~ Word -/-
|CAMPOS2|
        DCD     |CAMERAPOSX|
|RETFROMDRAWOBJECT|
        DCD     &00000000                       ; Word r/w (referenced)
        DCD     &00000000                       ;~ Word -/-
|OBJDIST|
        DCD     &00000000                       ; Word r/w (referenced)
|SRCCOORDSPLUS16|
        DCD     (MemSrcCoords+&10)                       ; Word r/- (referenced)
|SRCCOORDS|
        DCD     MemSrcCoords                       ; Word r/- (referenced)
|LINECOORDS5|
        DCD     MemLineCoords                       ; Word r/- (referenced)
|LINECOORDS2|
        DCD     &0002FDC0                       ; Word r/- (referenced)
        DCD     &000303B4                       ;~~ Word -/-
|OBJ3D2|
        DCD     MemObj3DAddrArray                       ; Word r/- (referenced)
|PROTATIONMATRIX|
        DCD     |ROTATIONMATRIX|

|CLIPPOLYGON|
        ; R8 = no. of clipped vertices in polygon
        ; R12 = no. of vertices in polygon
        CMP     R8,R12                          ; Function entry, (alters flags)
        BGE     |DRAWNEXTPOLYGON|

        STR     R14,|RETURNFROMCLIPPOLYGON|                 ; -> Word: &00000000

        LDR     R10,|LINECOORDS5|                 ; -> Word: MemLineCoords
        LDMIA   R10,{R0-R5}

        MOV     R9,R12,LSL #VertDataSizeALog2
        ADD     R9,R9,R12,LSL #VertDataSizeBLog2
        ADD     R9,R9,R10
        STMIA   R9!,{R0-R2}

        SUB     R8,R8,#1
        SUB     R12,R12,R8
        LDR     R11,|LINECOORDS2|                 ; -> Word: &0002FDC0

        LDR     R14,|CLIPY|                 ; -> Word: &00000000
        CMP     R1,R14
        BLT     |L0000C950| ; y0 < clip-y

        CMP     R4,R14
        BLT     |EXITCLIPLOOP4| ; y1 < clip-y

        STMIA   R11!,{R0-R2}
|CLIPLOOP4|
        ADD     R10,R10,#&0C                    ; =12
        LDMIA   R10,{R0-R5}
        CMP     R4,R14
        BLT     |EXITCLIPLOOP4|
        STMIA   R11!,{R0-R2}
        B       |CLIPLOOP4|                     ; Ends

|EXITCLIPLOOP4|
        BL      |CLIPLINEEND|
        STMIA   R11!,{R0-R5}
        LDR     R14,|CLIPY|                 ; -> Word: &00000000
|CLIPLOOP3|
        ADD     R10,R10,#&0C                    ; =12
        LDMIA   R10,{R0-R5}
        CMP     R4,R14
        BGE     |EXITCLIPLOOP3|
        B       |CLIPLOOP3|                     ; Ends

|EXITCLIPLOOP3|
        BL      |CLIPLINESTART|

        STMIA   R11!,{R0-R5}
        ADD     R10,R10,#&18                    ; =24
        LDMIA   R10!,{R0-R8}
        STMIA   R11!,{R0-R8}
        LDMIA   R10!,{R0-R8}
        STMIA   R11!,{R0-R8}
        B       |COPYLINECOORDS|                     ; Ends

|L0000C950|
        CMP     R4,R14
        BGE     |EXITCLIPLOOP| ; y1 >= clip-y
|CLIPLOOP|
        ADD     R10,R10,#&0C                    ; =12
        LDMIA   R10,{R0-R5}
        CMP     R4,R14
        BGE     |EXITCLIPLOOP| ; y1 >= clip-y
        B       |CLIPLOOP|                     ; Ends

|EXITCLIPLOOP|
        BL      |CLIPLINESTART|
        STMIA   R11!,{R0-R5}
        LDR     R14,|CLIPY|                 ; -> Word: &00000000
|CLIPLOOP2|
        ADD     R10,R10,#&0C                    ; =12
        LDMIA   R10,{R0-R5}
        CMP     R4,R14
        BLT     |EXITCLIPLOOP2|

        STMIA   R11!,{R3-R5}
        B       |CLIPLOOP2|                     ; Ends

|EXITCLIPLOOP2|
        BL      |CLIPLINEEND|

        STMIA   R11!,{R3-R5}
        ADD     R10,R10,#&18                    ; =24
        LDMIA   R10!,{R0-R8}
        STMIA   R11!,{R0-R8}
        LDMIA   R10!,{R0-R8}
        STMIA   R11!,{R0-R8}
|COPYLINECOORDS|
        LDR     R14,|CLIPY|                 ; -> Word: &00000000
        LDR     R10,|LINECOORDS2|                 ; -> Word: &0002FDC0
        LDR     R11,|LINECOORDS5|                 ; -> Word: MemLineCoords
        MOV     R9,#0
|COPYLINECOORDSLOOP|
        LDMIA   R10!,{R0-R2}
        CMP     R1,R14
        STMGEIA R11!,{R0-R2}
        ADDGE   R9,R9,#1
        SUBS    R12,R12,#1
        BPL     |COPYLINECOORDSLOOP|

        MOV     R12,R9
        LDR     R14,|RETURNFROMCLIPPOLYGON|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|CLIPLINESTART|
        STMFD   R13!,{R0-R5,R14}                ; Function entry, (alters flags)

        LDR     R14,|CLIPY|                 ; -> Word: &00000000
        SUB     R8,R4,R14
        SUB     R1,R4,R1
        MOV     R8,R8,LSL #12
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R9,R3

        LDMFD   R13!,{R0-R5,R14}

        SUB     R6,R0,R3
        SUB     R7,R2,R5
        MUL     R0,R6,R9
        MUL     R2,R7,R9
        ADD     R0,R3,R0,ASR #12
        ADD     R2,R5,R2,ASR #12
        LDR     R1,|CLIPY|                  ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|CLIPLINEEND|
        STMFD   R13!,{R0-R5,R14}                ; Function entry, (alters flags)

        LDR     R14,|CLIPY|                 ; -> Word: &00000000
        SUB     R8,R1,R14
        SUB     R1,R1,R4
        MOV     R8,R8,LSL #12
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R9,R3

        LDMFD   R13!,{R0-R5,R14}

        SUB     R6,R3,R0
        SUB     R7,R5,R2
        MUL     R3,R6,R9
        MUL     R5,R7,R9
        ADD     R3,R0,R3,ASR #12
        ADD     R5,R2,R5,ASR #12
        LDR     R4,|CLIPY|                  ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|DRAW1STCOORDASPIXEL|
        LDR     R0,|SRCCOORDSPLUS16|                  ; -> Word: (MemSrcCoords+&10)
        LDMIA   R0,{R0-R2}

        CMP     R1,#&1E                         ; =30
        BLT     |RETFROM1STCOORDASPIXEL|

        MOV     R9,R4
        BL      |PROJECT3D| ; In R0-R2, out R0,R2

        LDR     R10,|MAXCOORDX|                 ; -> Word: &0000013F
        ADD     R0,R0,R10,LSL #(CoordToScreenLog2-1)
        MOV     R0,R0,ASR #CoordToScreenLog2
        CMP     R0,#0
        BLT     |RETFROM1STCOORDASPIXEL|

        CMP     R0,R10
        BGE     |RETFROM1STCOORDASPIXEL|

        LDR     R10,|MAXCOORDY|                 ; -> Word: &000000F2
        ADD     R2,R2,R10,LSL #(CoordToScreenLog2-1)
        MOV     R2,R2,ASR #CoordToScreenLog2

        CMP     R2,#1
        BLT     |RETFROM1STCOORDASPIXEL|

        CMP     R2,R10
        BGT     |RETFROM1STCOORDASPIXEL|

        LDR     R10,|FRAMEBUFFER98|                 ; -> Word: &00000000
        ADD     R10,R10,R0
        MOV     R3,R2,LSL #RowStrideALog2
        ADD     R3,R3,R2,LSL #RowStrideBLog2
        ADD     R10,R10,R3
        STRB    R4,[R10,#0]

|RETFROM1STCOORDASPIXEL|
        LDR     R14,|RETFROMDRAWOBJECT|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|PLOTPOINT|
        ; r0 = x screen coord
        ; r1 = y screen coord
        ; r4 = colour
        MOV     R2,R1                           ; Function entry, (alters flags)

        ; Translate coordinate origin to the middle of the screen
        LDR     R10,|MAXCOORDX|                 ; -> Word: &0000013F
        ADD     R0,R0,R10,LSL #(CoordToScreenLog2-1)
        MOV     R0,R0,ASR #CoordToScreenLog2
        CMP     R0,#0
        MOVLT   PC,R14                          ; Function exit if LT

        CMP     R0,R10
        MOVGE   PC,R14                          ; Function exit if GE

        LDR     R10,|MAXCOORDY|                 ; -> Word: &000000F2
        ADD     R2,R2,R10,LSL #(CoordToScreenLog2-1)
        MOV     R2,R2,ASR #CoordToScreenLog2
        CMP     R2,#1
        MOVLT   PC,R14                          ; Function exit if LT

        CMP     R2,R10
        MOVGT   PC,R14                          ; Function exit if GT

        LDR     R10,|FRAMEBUFFER98|                 ; -> Word: &00000000
        ADD     R10,R10,R0
        MOV     R3,R2,LSL #RowStrideALog2
        ADD     R3,R3,R2,LSL #RowStrideBLog2
        ADD     R10,R10,R3
        STRB    R4,[R10,#0]

        MOV     PC,R14                          ; Function exit, Ends

|POBJARRAY3|
        DCD     MemObjArray                       ; Word r/- (referenced)
|L0000CB2C|
        DCD     |ANOTHERNUMOBJMINUS1|
|OBJ3D3|
        DCD     MemObj3DAddrArray                       ; Word r/- (referenced)
|SRCCOORDSPLUS16B|
        DCD     (MemSrcCoords+&10)                       ; Word r/- (referenced)
|LINECOORDS6|
        DCD     MemLineCoords                       ; Word r/- (referenced)
|SRCCOORDSPLUS8|
        DCD     &0002E010                       ; Word r/- (referenced)
|RETFROMDRAWSCENERY|
        DCD     &00000000                       ; Word r/w (referenced)
|PMISSIONNUM6|
        DCD     |MISSIONNUM|
|INTERVALTIMERBLK2|
        DCD     |L0000B6B4.5_byte_Time|
|LOG2SCALE|
        DCD     &00000000                       ; Word r/w (referenced)

|DRAWSCENERYONMAP|
        ; r0 = frame buffer address + offset
        ; r12 = 2 player?
        STR     R14,|RETFROMDRAWSCENERY|                 ; -> Word: &00000000, Function entry, (alters flags)
        CMP     R12,#0
        MOVEQ   R12,#9
        MOVNE   R12,#&0A                        ; =10
        STR     R12,|LOG2SCALE|                 ; -> Word: &00000000
        STR     R0,|FRAMEBUFFER98|                  ; -> Word: &00000000

        LDR     R0,|MAXCOORDY|                  ; -> Word: &000000F2
        CMP     R0,#&96                         ; ="" (150)
        MOVGT   R0,#(HEIGHT-3)                         ; ="" (253)
        STRGT   R0,|MAXCOORDY|                  ; -> Word: &000000F2

        LDR     R1,|INTERVALTIMERBLK2|                  ; -> Word: &0001C824
        MOV     R4,#0
        STR     R4,[R1,#0]
        STR     R4,[R1,#4]
        MOV     R0,#WriteIntervalTimer
        SWI     OS_Word

        LDR     R0,|PMISSIONNUM6|                  ; -> Word: &000177B8
        LDR     R0,[R0,#0]
        CMP     R0,#3
        CMPNE   R0,#4
        CMPNE   R0,#&16                         ; =22
        BNE     |DRAWNOMAPSEA|

        LDR     R1,|LOG2SCALE|                  ; -> Word: &00000000
        CMP     R1,#&0A                         ; =10
        MOVEQ   R3,#&27                         ; ="'" (39)
        MOVNE   R3,#&4E                         ; ="N" (78)
        LDR     R0,|LINECOORDS6|                  ; -> Word: MemLineCoords
        MOV     R1,R3
        MOV     R2,#&96,30                      ; =&258
        STMIA   R0!,{R1,R2}
        MVN     R1,#&AF,30                      ; =&2BC
        STMIA   R0!,{R1,R2}
        MVN     R2,#&96,30                      ; =&258
        STMIA   R0!,{R1,R2}
        MOV     R1,R3
        STMIA   R0!,{R1,R2}

        LDR     R0,|LINECOORDS6|                  ; -> Word: MemLineCoords
        MOV     R1,#RoyalAzure
        MOV     R2,#PolygonStyleNoOutline
        MOV     R3,#0
        MOV     R12,#4 ; quadrilateral
        MOV     R3,#DrawPolygonMayDarken
        BL      |DRAWPOLYGON|

|DRAWNOMAPSEA|
        LDR     R0,|L0000CB2C|                  ; -> Word: &0001C7E4
        LDR     R0,[R0,#0]
        LDR     R1,|POBJARRAY3|                  ; -> Word: MemObjArray
|NEXTMAPOBJECT|
        LDR     R2,[R1,#ObjMesh] ; get object index
        CMP     R2,#MESH_GREY_CLOUD
        CMPNE   R2,#MESH_WHITE_CLOUD
        CMPNE   R2,#MESH_AIRSHIP
        CMPNE   R2,#MESH_BARRAGE_BALLOON
        CMPNE   R2,#MESH_TRAIN
        CMPNE   R2,#MESH_GUN_BOAT
        CMPNE   R2,#MESH_OIL_TANKER
        CMPNE   R2,#MESH_FIELD_BOUNDARY          ; ="L" (76)
        CMPNE   R2,#MESH_RUBBISH
        ADD     R1,R1,#ObjCoord                 ; =12
        BEQ     |SKIPMAPOBJECT|

        CMP     R2,#MESH_PATROL_BOAT
        BLE     |SKIPMAPOBJECT|

        CMP     R2,#MESH_JET_FIGHTER ; bug?

        MOV     R14,R2
        LDR     R3,|OBJ3D3|                  ; -> Word: MemObj3DAddrArray
        ADD     R2,R3,R2,LSL #BytesPerAddressLog2
        LDR     R2,[R2,#0] ; get address of object mesh
        LDMIA   R2,{R3-R5} ; MeshSimplifyDist, MeshPrimCountMinus1, MeshVertCountMinus1

        LDMIA   R1,{R10-R12} ; get object coordinates (z is ignored)
        ADD     R2,R2,#BytesPerMeshHdr      ; =" " (32)
        LDR     R6,|SRCCOORDSPLUS16B|                  ; -> Word: (MemSrcCoords+&10)
        LDR     R9,|LOG2SCALE|                  ; -> Word: &00000000
|XFORMPOSLOOP|
        LDMIA   R2!,{R7,R8} ; get VertX, VertY from mesh
        ADD     R2,R2,#(VertZ-VertY)
        ADD     R7,R7,R10 ; translate vertex x,y to object position
        ADD     R8,R8,R11
        MVN     R7,R7,ASR R9 ; -x
        MOV     R8,R8,ASR R9 ; y
        STMIA   R6!,{R7,R8} ; store translated vertex x,y
        SUBS    R5,R5,#1 ; next vertex
        BPL     |XFORMPOSLOOP|

        STMFD   R13!,{R0,R1}
        ; The following objects are not simplified
        CMP     R14,#MESH_ISLAND                        ; ="0" (48)
        CMPNE   R14,#MESH_AERODROME                     ; ="9" (57)
        CMPNE   R14,#MESH_AIRCRAFT_CARRIER_2            ; ="2" (50)
        CMPNE   R14,#MESH_AIRCRAFT_CARRIER_3            ; ="3" (51)
        CMPNE   R14,#MESH_DARK_OLIVE_FIELD_1            ; =":" (58)
        CMPNE   R14,#MESH_DARK_OLIVE_FIELD_2            ; =";" (59)
        CMPNE   R14,#MESH_AERODROME_2                   ; =""" (34)
        BEQ     |DRAWPOLYGONLOOP|

        MOV     R4,#0 ; only one polygon
|DRAWPOLYGONLOOP|
        LDMIA   R2!,{R6-R9} ; load vertex indices
        LDR     R3,|SRCCOORDSPLUS8|                  ; -> Word: &0002E010
        LDR     R5,|LINECOORDS6|                  ; -> Word: MemLineCoords
        MOV     R9,#2 ; start with two edges

        MOV     R10,R6,LSL #24
        MOV     R10,R10,LSR #24
        ADD     R10,R3,R10,LSL #3
        LDMIA   R10,{R11,R12} ; x,y
        STMIA   R5!,{R11,R12}

        MOV     R10,R6,LSL #16
        MOV     R10,R10,LSR #24
        ADD     R10,R3,R10,LSL #3
        LDMIA   R10,{R11,R12}
        STMIA   R5!,{R11,R12}

        MOV     R10,R6,LSL #8
        MOV     R10,R10,LSR #24
        CMP     R10,#VertexEnd
        BEQ     |NOTAVERTEX|

        CMP     R10,#MaxVertexNum                        ; ="" (200)
        BGT     |NOTAVERTEX|

        ADD     R10,R3,R10,LSL #3
        LDMIA   R10,{R11,R12}
        STMIA   R5!,{R11,R12}
        ADD     R9,R9,#1 ; another edge

        MOV     R10,R6,LSR #24
        CMP     R10,#VertexEnd
        BEQ     |NOTAVERTEX|

        CMP     R10,#MaxVertexNum                        ; ="" (200)
        BGT     |NOTAVERTEX|

        ADD     R10,R3,R10,LSL #3
        LDMIA   R10,{R11,R12}
        STMIA   R5!,{R11,R12}
        ADD     R9,R9,#1 ; another edge

        MOV     R10,R7,LSL #24
        MOV     R10,R10,LSR #24
        CMP     R10,#VertexEnd
        BEQ     |NOTAVERTEX|

        CMP     R10,#MaxVertexNum                        ; ="" (200)
        BGT     |NOTAVERTEX|

        ADD     R10,R3,R10,LSL #3
        LDMIA   R10,{R11,R12}
        STMIA   R5!,{R11,R12}
        ADD     R9,R9,#1 ; another edge

        MOV     R10,R7,LSL #16
        MOV     R10,R10,LSR #24
        CMP     R10,#VertexEnd
        BEQ     |NOTAVERTEX|

        CMP     R10,#MaxVertexNum                        ; ="" (200)
        BGT     |NOTAVERTEX|

        ADD     R10,R3,R10,LSL #3
        LDMIA   R10,{R11,R12}
        STMIA   R5!,{R11,R12}
        ADD     R9,R9,#1 ; another edge

        MOV     R10,R7,LSL #8
        MOV     R10,R10,LSR #24
        CMP     R10,#VertexEnd
        BEQ     |NOTAVERTEX|

        CMP     R10,#MaxVertexNum                        ; ="" (200)
        BGT     |NOTAVERTEX|

        ADD     R10,R3,R10,LSL #3
        LDMIA   R10,{R11,R12}
        STMIA   R5!,{R11,R12}
        ADD     R9,R9,#1 ; another edge

        MOV     R10,R7,LSR #24
        CMP     R10,#VertexEnd
        BEQ     |NOTAVERTEX|

        CMP     R10,#MaxVertexNum                        ; ="" (200)
        BGT     |NOTAVERTEX|

        ADD     R10,R3,R10,LSL #3
        LDMIA   R10,{R11,R12}
        STMIA   R5!,{R11,R12}
        ADD     R9,R9,#1 ; another edge
|NOTAVERTEX|
        STMFD   R13!,{R2,R4}
        LDR     R0,|LINECOORDS6|                  ; -> Word: MemLineCoords
        MOV     R1,R8,LSL #24
        MOV     R1,R1,LSR #24
        MOV     R2,#PolygonStyleNoOutline
        MOV     R12,R9 ; no. of lines
        MOV     R3,#DrawPolygonMayDarken
        BL      |DRAWPOLYGON|

        LDMFD   R13!,{R2,R4}
        SUBS    R4,R4,#1
        BPL     |DRAWPOLYGONLOOP|

        LDMFD   R13!,{R0,R1}
|SKIPMAPOBJECT|
        SUBS    R0,R0,#1
        ADD     R1,R1,#(BytesPerObj - ObjCoord); next in POBJARRAY
        BPL     |NEXTMAPOBJECT|

|WAITFORTIMERLOOP|
        LDR     R1,|INTERVALTIMERBLK2|                  ; -> Word: &0001C824
        MOV     R4,#0
        MOV     R0,#ReadIntervalTimer
        SWI     OS_Word

        LDR     R1,|INTERVALTIMERBLK2|                  ; -> Word: &0001C824
        LDRB    R1,[R1,#0]
        CMP     R1,#MinCentisecondsPerFrame
        BLT     |WAITFORTIMERLOOP|

        LDR     R14,|RETFROMDRAWSCENERY|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|MAXCOORDY|
        DCD     HeightExclFrontBottomWing                  ; Word r/w (referenced)
|MAXCOORDX|
        DCD     WIDTH-1                     ; Word r/- (referenced)
        DCD     &00000000                       ;~ Word -/-
|SPANADDRTABLE|
        DCD     MemSpanPointerArray                       ; Word r/- (referenced)
|SPANSTARTORENDTABLE|
        DCD     MemSpanStartEnd                       ; Word r/- (referenced)
|RETFROMDRAWEDGE|
        DCD     &00000000                       ; Word r/w (referenced)
        DCD     VDUVarDisplayStart                       ;~~ Word -/-
        DCD     VDUVarEndOfList                       ;~ Word -/-
|FRAMEBUFFER98|
        DCD     &00000000                       ; Word r/w (referenced)
        DCD     &00000000                       ;~ Word -/-

|DRAWEDGE|
        ;r0,r2 x
        ;r1,r3 y span indices
        ;r4 colour
        STR     R14,|RETFROMDRAWEDGE|                 ; -> Word: &00000000, Function entry

        ; Translate coordinate origin to the middle of the screen
        LDR     R10,|MAXCOORDX|                 ; -> Word: &0000013F
        ADD     R0,R0,R10,LSL #(CoordToScreenLog2-1)
        MOV     R0,R0,ASR #CoordToScreenLog2
        ADD     R2,R2,R10,LSL #(CoordToScreenLog2-1)
        MOV     R2,R2,ASR #CoordToScreenLog2

        LDR     R12,|MAXCOORDY|                 ; -> Word: &000000F2
        ADD     R1,R1,R12,LSL #(CoordToScreenLog2-1)
        ADD     R3,R3,R12,LSL #(CoordToScreenLog2-1)
        MOV     R3,R3,ASR #CoordToScreenLog2
        MOV     R1,R1,ASR #CoordToScreenLog2

        CMP     R0,#0
        CMPLT   R2,#0
        BLT     |L0000D23C|

        CMP     R0,R10
        CMPGE   R2,R10
        BGE     |L0000D234|

        STMFD   R13!,{R0-R3}
        CMP     R1,#0
        BLLT    |CLIPEDGETOMINY|

        LDR     R12,|MAXCOORDY|                 ; -> Word: &000000F2
        CMP     R1,R12
        BLGT    |CLIPEDGETOMAXY|

        SWAP    R0,R2,R6
        SWAP    R1,R3,R6

        CMP     R1,#0
        BLLT    |CLIPEDGETOMINY|

        LDR     R12,|MAXCOORDY|                 ; -> Word: &000000F2
        CMP     R1,R12
        BLGT    |CLIPEDGETOMAXY|

        CMP     R0,#0
        BLLT    |CLIPEDGETOMINX|

        CMP     R0,R10
        BLGT    |CLIPEDGETOMAXX|

        SWAP    R0,R2,R6
        SWAP    R1,R3,R6

        CMP     R0,#0
        BLLT    |CLIPEDGETOMINX|

        CMP     R0,R10
        BLGT    |CLIPEDGETOMAXX|

        CMP     R3,R1
        BLE     |L0000CF40|

        SWAP    R0,R2,R5
        SWAP    R1,R3,R5

|L0000CF40|
        SUBS    R7,R2,R0
        RSBMI   R9,R7,#0 ; r9 = abs(r7)
        MOVPL   R9,R7

        SUBS    R8,R3,R1
        RSBMI   R10,R8,#0 ; r10 = abs(r8)
        MOVPL   R10,R8

        LDR     R11,|TOPSPANINDEX|                 ; -> Word array: &00000000
        CMP     R1,R11
        STRGT   R1,|TOPSPANINDEX|                  ; -> Word array: &00000000
        LDR     R11,|BOTSPANINDEX|                 ; -> Word array: &00000000
        CMP     R3,R11
        STRLT   R3,|BOTSPANINDEX|                  ; -> Word array: &00000000
        CMP     R9,#0
        CMPEQ   R10,#0
        CMPEQ   R9,#0 ; bug: redundant
        BEQ     |L0000D134|

        CMP     R9,R10
        BLT     |L0000D058|

        STMFD   R13!,{R0-R4}

        MOV     R1,R9
        MOV     R8,R10,LSL #FixedPointOneLog2
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R12,R3

        LDMFD   R13,{R0-R4}

        MOV     R1,R1,LSL #FixedPointOneLog2
        LDR     R11,|FRAMEBUFFER98|                 ; -> Word: &00000000
        MOV     R9,#WIDTH
        LDR     R6,|SPANADDRTABLE|                  ; -> Word: MemSpanPointerArray
        MVN     R5,#&64                         ; ="d" (100)
        MOV     R7,R1,ASR #FixedPointOneLog2
        CMP     R0,R2
        MVNGT   R14,#0
        MOVLE   R14,#1
        STR     R2,|L0000D054|                  ; -> Word: &00000000

        LDR     R2,|SPANSTARTORENDTABLE|                  ; -> Word: MemSpanStartEnd
|L0000CFCC|
        ADD     R10,R11,R0
        MOV     R8,R7,LSL #RowStrideALog2
        ADD     R8,R8,R7,LSL #RowStrideBLog2
        ADD     R10,R10,R8
        CMP     R5,R7
        BEQ     |L0000D000|

        MOV     R5,R7,LSL #BytesPerAddressLog2
        LDRB    R8,[R2,R7]
        CMP     R8,#0 ; start or end?
        STREQ   R10,[R6,R5] ; start of span address
        STREQB  R14,[R2,R7]
        ADDNE   R5,R5,#MaxSpans                   ; =&400
        STRNE   R10,[R6,R5] ; end of span address
|L0000D000|
        MOV     R5,R7
        STRB    R4,[R10,#0]
        SUB     R1,R1,R12 ; always up screen
        ADD     R0,R0,R14 ; left or right?
        MOV     R7,R1,ASR #FixedPointOneLog2
        CMP     R7,R3
        BGT     |L0000CFCC|

        LDR     R3,|L0000D054|                  ; -> Word: &00000000
|DRAWPIXELLOOP|
        ADD     R10,R11,R0
        MOV     R8,R7,LSL #RowStrideALog2
        ADD     R8,R8,R7,LSL #RowStrideBLog2
        ADD     R10,R10,R8
        STRB    R4,[R10,#0]
        SUB     R1,R1,R12
        ADD     R0,R0,R14
        MOV     R7,R1,ASR #FixedPointOneLog2
        CMN     R14,#1
        CMPGT   R0,R3
        CMPEQ   R3,R0
        BLE     |DRAWPIXELLOOP|

        B       |L0000D0E0|                     ; Ends

|L0000D054|
        DCD     &00000000                       ; Word r/w (referenced)

|L0000D058|
        CMP     R1,R3
        RSBGT   R8,R8,#0

        STMFD   R13!,{R0-R4}

        MOV     R1,R8
        MOV     R8,R7,LSL #FixedPointOneLog2
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R12,R3

        LDMFD   R13,{R0-R4}

        MOV     R0,R0,LSL #FixedPointOneLog2
        LDR     R11,|FRAMEBUFFER98|                 ; -> Word: &00000000
        MOV     R9,#1
        LDR     R6,|SPANADDRTABLE|                  ; -> Word: MemSpanPointerArray
        LDR     R2,|SPANSTARTORENDTABLE|                  ; -> Word: MemSpanStartEnd
|L0000D08C|
        ; R0 = screen x coord * 8192
        ; R1 = screen y coord
        ADD     R10,R11,R0,ASR #FixedPointOneLog2
        MOV     R8,R1,LSL #RowStrideALog2
        ADD     R8,R8,R1,LSL #RowStrideBLog2
        ADD     R10,R10,R8
        MOV     R5,R1,LSL #BytesPerAddressLog2
        LDRB    R8,[R2,R1]
        CMP     R8,#0 ; start or end?
        STREQ   R10,[R6,R5]
        STREQB  R9,[R2,R1] ; start of span address
        ADDNE   R5,R5,#MaxSpans                   ; =&400
        STRNE   R10,[R6,R5] ; end of span address
        STRB    R4,[R10,#0]

        SUB     R1,R1,#1
        ADD     R0,R0,R12
        CMP     R1,R3
        BGT     |L0000D08C|

        ADD     R10,R11,R0,ASR #FixedPointOneLog2
        MOV     R8,R1,LSL #RowStrideALog2
        ADD     R8,R8,R1,LSL #RowStrideBLog2
        ADD     R10,R10,R8
        STRB    R4,[R10,#0]
|L0000D0E0|
        LDMFD   R13,{R0-R8}
        ADD     R13,R13,#&14                    ; =20
        CMP     R8,R6
        BLE     |L0000D108|

        MOV     R9,R5
        MOV     R5,R7
        MOV     R7,R9

        MOV     R9,R6
        MOV     R6,R8
        MOV     R8,R9
|L0000D108|
        CMP     R6,R1
        BLNE    |L0000D154|
        CMP     R8,R3
        BLNE    |L0000D1C4|
|L0000D118|
        ADD     R13,R13,#&10                    ; =16
        LDR     R14,|RETFROMDRAWEDGE|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|L0000D124|
        ADD     R13,R13,#&10                    ; =16
        CMP     R0,#&32                         ; ="2" (50)
        BGT     |L0000D234|
        B       |L0000D23C|                     ; Ends

|L0000D134|
        ; R0 = screen x coord
        ; R1 = screen y coord
        STMFD   R13!,{R0-R4}
        LDR     R10,|FRAMEBUFFER98|                 ; -> Word: &00000000
        ADD     R10,R10,R0
        MOV     R8,R1,LSL #RowStrideALog2
        ADD     R8,R8,R1,LSL #RowStrideBLog2
        ADD     R10,R10,R8
        STRB    R4,[R10,#0]
        B       |L0000D0E0|                     ; Ends

|L0000D154|
        LDR     R9,|FRAMEBUFFER98|                  ; -> Word: &00000000, Function entry, (alters flags)
        LDR     R10,|SPANADDRTABLE|                 ; -> Word: MemSpanPointerArray
        CMP     R5,#&32                         ; ="2" (50)
        LDRGT   R5,|MAXCOORDX|                  ; -> Word: &0000013F
        ADDGT   R9,R9,R5
        SUBLE   R9,R9,#1

        LDR     R5,|SPANSTARTORENDTABLE|                  ; -> Word: MemSpanStartEnd
        CMP     R6,#(HEIGHT-3)                         ; ="" (253)
        MOVGT   R6,#(HEIGHT-3)                         ; ="" (253)
        CMPGE   R1,#(HEIGHT-3)                         ; ="" (253)
        MOVGE   PC,R14                          ; Function exit if GE

        LDR     R11,|TOPSPANINDEX|                 ; -> Word array: &00000000
        CMP     R6,R11
        STRGT   R6,|TOPSPANINDEX|                  ; -> Word array: &00000000
|L0000D18C|
        MOV     R11,R6,LSL #RowStrideALog2
        ADD     R11,R11,R6,LSL #RowStrideBLog2
        ADD     R11,R11,R9
        LDRB    R12,[R5,R6]
        CMP     R12,#0 ; start or end?
        MOV     R12,R6,LSL #BytesPerAddressLog2
        STREQ   R11,[R10,R12] ; start of span address
        STREQB  R6,[R5,R6]
        ADDNE   R12,R12,#MaxSpans                 ; =&400
        STRNE   R11,[R10,R12] ; end of span address

        SUB     R6,R6,#1
        CMP     R6,R1
        BGT     |L0000D18C|

        MOV     PC,R14                          ; Function exit, Ends

|L0000D1C4|
        LDR     R9,|FRAMEBUFFER98|                  ; -> Word: &00000000, Function entry, (alters flags)
        LDR     R10,|SPANADDRTABLE|                 ; -> Word: MemSpanPointerArray
        CMP     R7,#&32                         ; ="2" (50)
        LDRGT   R5,|MAXCOORDX|                  ; -> Word: &0000013F
        ADDGT   R9,R9,R5
        SUBLE   R9,R9,#1

        LDR     R5,|SPANSTARTORENDTABLE|                  ; -> Word: MemSpanStartEnd
        ADD     R8,R8,#1
        CMP     R8,#0
        MOVLT   R8,#0

        LDR     R11,|BOTSPANINDEX|                 ; -> Word array: &00000000
        CMP     R8,R11
        STRLT   R8,|BOTSPANINDEX|                  ; -> Word array: &00000000

        MOV     R7,#1
|L0000D1FC|
        MOV     R11,R8,LSL #RowStrideALog2
        ADD     R11,R11,R8,LSL #RowStrideBLog2
        ADD     R11,R11,R9

        LDRB    R12,[R5,R8]
        CMP     R12,#0 ; start or end?
        MOV     R12,R8,LSL #BytesPerAddressLog2
        STREQ   R11,[R10,R12] ; start of span address
        STREQB  R7,[R5,R8]
        ADDNE   R12,R12,#MaxSpans                 ; =&400
        STRNE   R11,[R10,R12] ; end of span address

        ADD     R8,R8,#1
        CMP     R8,R3
        BLE     |L0000D1FC|

        MOV     PC,R14                          ; Function exit, Ends

|L0000D234|
        MOV     R11,R10
        B       |L0000D240|                     ; Ends

|L0000D23C|
        MVN     R11,#0
|L0000D240|
        CMP     R3,R1
        SWAPIF  GT,R3,R1,R4

        MOV     R12,#1
        CMP     R1,#(HEIGHT-3)                         ; ="" (253)
        CMPGT   R3,#(HEIGHT-3)                         ; ="" (253)
        BGT     |L0000D2DC|

        CMP     R1,#0
        CMPLT   R3,#0
        BLT     |L0000D2DC|

        CMP     R1,#(HEIGHT-3)                         ; ="" (253)
        MOVGT   R1,#(HEIGHT-3)                         ; ="" (253)

        ADD     R3,R3,#1
        CMP     R3,#0
        MOVLT   R3,#0

        LDR     R5,|FRAMEBUFFER98|                  ; -> Word: &00000000
        ADD     R5,R5,R11
        LDR     R6,|SPANADDRTABLE|                  ; -> Word: MemSpanPointerArray
        LDR     R8,|SPANSTARTORENDTABLE|                  ; -> Word: MemSpanStartEnd

        LDR     R11,|BOTSPANINDEX|                 ; -> Word array: &00000000
        CMP     R3,R11
        STRLT   R3,|BOTSPANINDEX|                  ; -> Word array: &00000000

        LDR     R11,|TOPSPANINDEX|                 ; -> Word array: &00000000
        CMP     R1,R11
        STRGT   R1,|TOPSPANINDEX|                  ; -> Word array: &00000000
|L0000D2A8|
        MOV     R11,R1,LSL #RowStrideALog2
        ADD     R11,R11,R1,LSL #RowStrideBLog2
        ADD     R11,R11,R5
        MOV     R4,R1,LSL #BytesPerAddressLog2
        LDRB    R7,[R8,R1]
        CMP     R7,#0 ; start or end?
        STREQ   R11,[R6,R4] ; start of span address
        STREQB  R12,[R8,R1]
        ADDNE   R4,R4,#MaxSpans                   ; =&400
        STRNE   R11,[R6,R4]  ; end of span address
        SUB     R1,R1,#1
        CMP     R1,R3
        BGE     |L0000D2A8|
|L0000D2DC|
        LDR     R14,|RETFROMDRAWEDGE|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|CLIPEDGETOMINX|
        MOV     R11,R14                         ; Function entry, (alters flags)
        CMP     R2,#0
        BLT     |L0000D124|

        STMFD   R13!,{R0-R4}

        SUB     R8,R2,#0
        MOV     R8,R8,LSL #FixedPointOneLog2
        SUB     R1,R2,R0
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R5,R3

        LDMFD   R13!,{R0-R4}

        MOV     R0,#0
        SUB     R6,R3,R1
        MUL     R7,R5,R6
        MOV     R7,R7,ASR #FixedPointOneLog2
        SUB     R1,R3,R7

        MOV     PC,R11                          ; Ends, Dynamic branch

|CLIPEDGETOMAXX|
        MOV     R11,R14                         ; Function entry
        CMP     R2,R10
        BGT     |L0000D124|

        STMFD   R13!,{R0-R4}

        RSB     R8,R2,R10
        MOV     R8,R8,LSL #FixedPointOneLog2
        SUB     R1,R0,R2
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R5,R3

        LDMFD   R13!,{R0-R4}

        MOV     R0,R10
        SUB     R6,R3,R1
        MUL     R7,R5,R6
        MOV     R7,R7,ASR #FixedPointOneLog2
        SUB     R1,R3,R7

        MOV     PC,R11                          ; Ends, Dynamic branch

|CLIPEDGETOMINY|
        MOV     R11,R14                         ; Function entry, (alters flags)
        CMP     R3,#0
        BLT     |L0000D118|

        STMFD   R13!,{R0-R4}

        SUB     R8,R3,#0
        MOV     R8,R8,LSL #FixedPointOneLog2
        SUB     R1,R3,R1
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R5,R3

        LDMFD   R13!,{R0-R4}

        MOV     R1,#0
        SUB     R6,R2,R0
        MUL     R7,R5,R6
        MOV     R7,R7,ASR #FixedPointOneLog2
        SUB     R0,R2,R7

        MOV     PC,R11                          ; Ends, Dynamic branch

|CLIPEDGETOMAXY|
        MOV     R11,R14                         ; Function entry
        CMP     R3,R12
        BGT     |L0000D118|
        STMFD   R13!,{R0-R4}
        RSB     R8,R3,R12
        MOV     R8,R8,LSL #FixedPointOneLog2
        SUB     R1,R1,R3
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R5,R3
        LDMFD   R13!,{R0-R4}
        LDR     R1,|MAXCOORDY|                  ; -> Word: &000000F2
        SUB     R6,R2,R0
        MUL     R7,R5,R6
        MOV     R7,R7,ASR #FixedPointOneLog2
        SUB     R0,R2,R7
        MOV     PC,R11                          ; Ends, Dynamic branch

|SPANSTARTORENDINIT|
        DCD     &00000000                       ; Word array r/- (referenced)
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array r/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
|SPANADDRTABLE2|
        DCD     MemSpanPointerArray                       ;~~~ Word array r/- (referenced)
        DCD     &00000000                       ;~~~ Word array -/-
|SPANSTARTORENDTABLE2|
        DCD     MemSpanStartEnd                       ;~~~ Word array r/- (referenced)
|RETFROMDRAWPOLYGON|
        DCD     &00000000                       ;~~~ Word array r/w (referenced)
|LINECOORDS|
        DCD     &00000000                       ;~~~ Word array r/w (referenced)
        DCD     &00000000                       ;~~~ Word array -/-
|TOPSPANINDEX|
        DCD     &00000000                       ;~~~ Word array r/w (referenced)
|BOTSPANINDEX|
        DCD     &00000000                       ;~~~ Word array r/w (referenced)
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
        DCD     &00000000                       ;~~~ Word array -/-
|FILLCOLOUR|
        DCD     &00000064                       ;~~~ Word array r/w (referenced)
|LINECOLOUR|
        DCD     &00000000                       ;~~~ Word array r/w (referenced)
|NLINES|
        DCD     &00000000                       ;~~~ Word array r/w (referenced)
|LINECOUNT|
        DCD     &00000000                       ;~~~ Word array r/w (referenced)

|ADJUSTCOLFORNIGHT|
        LDR     R5,|ISNIGHTMISSION|                  ; -> Word: &00000000, Function entry, (alters flags)
        CMP     R5,#0
        MOVEQ   PC,R14                          ; Function exit if EQ

        LDR     R5,|LIGHTNINGFLASH|                  ; -> Word: &00000000
        CMP     R5,#0
        MOVNE   PC,R14                          ; Function exit if NE

        BIC     R4,R4,#1
        TST     R4,#RedHi                        ; =16
        BICNE   R4,R4,#RedHi + RedLo                      ; =20
        ADDNE   R4,R4,#RedLo

        TST     R4,#GreenHi                        ; ="@" (64)
        BICNE   R4,R4,#GreenHi + GreenLo                      ; ="`" (96)
        ADDNE   R4,R4,#GreenLo                     ; =" " (32)

        TST     R4,#BlueHi                         ; ="" (128)
        BICNE   R4,R4,#BlueHi + BlueLo                      ; ="" (136)
        ADDNE   R4,R4,#BlueLo

        TST     R4,#TintHi
        BICNE   R4,R4,#TintHi + TintLo
        ADDNE   R4,R4,#TintLo

        MOV     PC,R14                          ; Function exit, Ends

|ISNIGHTMISSION|
        DCD     &00000000                       ; Word r/- (referenced)
|LIGHTNINGFLASH|
        DCD     &00000000                       ; Word r/- (referenced)

|DRAWPOLYGON|
; Parameters R0-R3, R12
; R0 = line coordinates
; R1 = plot colour
; R2 = outline colour (none, black or blue)
; R3 = Whether or not to allow colour adjustment
; R12 = number of lines
        STR     R14,|RETFROMDRAWPOLYGON|                 ; -> Word array: &00000000, Function entry, (alters flags)

        LDR     R4,|ISNIGHTMISSION|                  ; -> Word: &00000000
        CMP     R4,#0
        CMPNE   R3,#DrawPolygonNoDarken                         ; ="c" (99)
        BEQ     |NOTNIGHT|

        LDR     R4,|LIGHTNINGFLASH|                  ; -> Word: &00000000
        CMP     R4,#0
        BNE     |NOTNIGHT|

        BIC     R1,R1,#TintLo
        ; If high bits are set then clear and set low bits
        TST     R1,#RedHi                        ; =16
        BICNE   R1,R1,#RedHi + RedLo                      ; =20
        ADDNE   R1,R1,#RedLo
        TST     R1,#GreenHi                        ; ="@" (64)
        BICNE   R1,R1,#GreenHi + GreenLo           ; ="`" (96)
        ADDNE   R1,R1,#GreenLo                     ; =" " (32)
        TST     R1,#BlueHi                         ; ="" (128)
        BICNE   R1,R1,#BlueHi + BlueLo                      ; ="" (136)
        ADDNE   R1,R1,#BlueLo
        TST     R1,#TintHi
        BICNE   R1,R1,#TintHi + TintLo
        ADDNE   R1,R1,#TintLo

|NOTNIGHT|
        STR     R0,|LINECOORDS|                  ; -> Word array: &00000000
        STR     R1,|FILLCOLOUR|                  ; -> Word array: &00000064
        STR     R12,|NLINES|                 ; -> Word array: &00000000

        CMP     R2,#PolygonStyleBlackOutline
        MOVEQ   R1,#Black
        MOVGT   R1,#RoyalAzure
        STR     R1,|LINECOLOUR|                  ; -> Word array: &00000000

        LDMIA   R0,{R3,R4} ; Copy first coords as last coords
        ADD     R0,R0,R12,LSL #3
        STMIA   R0,{R3,R4}

        MVN     R0,#MaxSpans                      ; =&400
        STR     R0,|TOPSPANINDEX|                  ; -> Word array: &00000000

        MOV     R0,#MaxSpans                      ; =&400
        STR     R0,|BOTSPANINDEX|                  ; -> Word array: &00000000

        ADR     R0,|SPANSTARTORENDINIT|                  ; -> Word array: &00000000
        LDMIA   R0,{R1-R12,R14}

        LDR     R0,|SPANSTARTORENDTABLE2|                  ; -> Word array: MemSpanStartEnd
        STMIA   R0!,{R1-R12,R14}
        STMIA   R0!,{R1-R12,R14}
        STMIA   R0!,{R1-R12,R14}
        STMIA   R0!,{R1-R12,R14}
        STMIA   R0!,{R1-R12,R14}

        LDR     R6,|LINECOORDS|                  ; -> Word array: &00000000
        LDMIA   R6,{R0-R3}
        LDR     R4,|LINECOLOUR|                  ; -> Word array: &00000000
        BL      |DRAWEDGE| ; In R0-R3 coords, R4 colour

        LDR     R6,|LINECOORDS|                  ; -> Word array: &00000000
        ADD     R6,R6,#8
        LDMIA   R6,{R0-R3}
        LDR     R4,|LINECOLOUR|                  ; -> Word array: &00000000
        BL      |DRAWEDGE| ; In R0-R3 coords, R4 colour

        LDR     R0,|NLINES|                  ; -> Word array: &00000000
        CMP     R0,#2
        BEQ     |NOSPANSTODRAW|

        MOV     R0,#2
        STR     R0,|LINECOUNT|                  ; -> Word array: &00000000

        LDR     R6,|LINECOORDS|                  ; -> Word array: &00000000
        ADD     R6,R6,#&10                      ; =16
        STR     R6,|LINECOORDS|                  ; -> Word array: &00000000
|DRAWEDGELOOP|
        LDR     R6,|LINECOORDS|                  ; -> Word array: &00000000
        LDMIA   R6,{R0-R3}
        LDR     R4,|LINECOLOUR|                  ; -> Word array: &00000000
        BL      |DRAWEDGE| ; In R0-R3 coords, R4 colour

        LDR     R6,|LINECOORDS|                  ; -> Word array: &00000000
        ADD     R6,R6,#8
        STR     R6,|LINECOORDS|                  ; -> Word array: &00000000

        LDR     R0,|NLINES|                  ; -> Word array: &00000000
        LDR     R1,|LINECOUNT|                  ; -> Word array: &00000000
        ADD     R1,R1,#1
        CMP     R1,R0
        STRLT   R1,|LINECOUNT|                  ; -> Word array: &00000000
        BLT     |DRAWEDGELOOP|

        LDR     R5,|FILLCOLOUR|                  ; -> Word array: &00000064
        ADD     R5,R5,R5,LSL #8
        ADD     R5,R5,R5,LSL #16 ; stretch the plot colour to four pixels
        MOV     R6,R5
        MOV     R7,R5
        MOV     R8,R5
        MOV     R9,R5
        MOV     R10,R5
        MOV     R11,R5
        MOV     R12,R5 ; stretch the plot colour to 32 pixels
        LDR     R2,|SPANADDRTABLE2|                  ; -> Word array: MemSpanPointerArray
        LDR     R0,|TOPSPANINDEX|                  ; -> Word array: &00000000
        LDR     R3,|MAXCOORDY|                  ; -> Word: &000000F2
        CMP     R0,R3
        MOVGT   R0,R3
        STRGT   R0,|TOPSPANINDEX|                  ; -> Word array: &00000000
        LDR     R0,|TOPSPANINDEX|                  ; -> Word array: &00000000
        SUB     R0,R0,#1
        LDR     R3,|BOTSPANINDEX|                  ; -> Word array: &00000000
        CMP     R0,R3
        BLT     |NOSPANSTODRAW|
        LDR     R0,|TOPSPANINDEX|                  ; -> Word array: &00000000
        ADD     R1,R2,R0,LSL #BytesPerAddressLog2 ; first span
        ADD     R0,R2,R3,LSL #BytesPerAddressLog2 ; last span
|DRAWSPANLOOP|
        LDR     R2,[R1,#0] ; start
        LDR     R3,[R1,#MaxSpans] ; end (up to 1024 spans?)
        CMP     R2,R3
        BEQ     |NEXTSPAN|

        CMP     R3,R2
        SWAPIF  LT,R3,R2,R4 ; swap start and end

        SUB     R3,R3,#1
        BIC     R4,R2,#3
        ADD     R4,R4,#4
        CMP     R4,R3
        BEQ     |DRAWOCTOWORDS|
        MOVGT   R4,R3

count SETA 0
        WHILE count < 4

        STRB    R5,[R2,#1]!
        CMP     R2,R4
        BGE     |DRAWOCTOWORDS|

count SETA count + 1
        WEND

|DRAWOCTOWORDS|
        SUB     R4,R3,#&20                      ; =" " (32)

        CMP     R2,R4
        BGT     |DRAWQUADWORDS|

count SETA 0
        WHILE count < 11

        STMIA   R2!,{R5-R12}
        CMP     R2,R4
        BGE     |DRAWQUADWORDS|

count SETA count + 1
        WEND

|DRAWQUADWORDS|
        SUB     R4,R3,#&10                      ; =16
        CMP     R2,R4
        STMLEIA R2!,{R5-R8}
        SUB     R4,R3,#8
        CMP     R2,R4
        STMLEIA R2!,{R5,R6}
        SUB     R4,R3,#4
        CMP     R2,R4
        BGT     |DRAWTRAILBYTES|

count SETA 0
        WHILE count < 8

        STR     R5,[R2,#0]
        ADD     R2,R2,#4
        CMP     R2,R4
        BGE     |DRAWTRAILBYTES|

count SETA count + 1
        WEND

|DRAWTRAILBYTES|
        CMP     R2,R3
        BGT     |NEXTSPAN|
        SUB     R2,R2,#1

count SETA 0
        WHILE count < 4

        STRB    R5,[R2,#1]!
        CMP     R2,R3
        BGE     |NEXTSPAN|

count SETA count + 1
        WEND

|NEXTSPAN|
        SUB     R1,R1,#4
        CMP     R1,R0
        BGT     |DRAWSPANLOOP|
|NOSPANSTODRAW|
        LDR     R14,|RETFROMDRAWPOLYGON|                 ; -> Word array: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|MAXCOORDY2|
        DCD     HeightExclFrontBottomWing                    ; Word r/- (referenced)
|MAXCOORDX2|
        DCD     WIDTH-1                       ; Word r/- (referenced)
|RETFROMDRAWLINE|
        DCD     &00000000                       ; Word r/w (referenced)
|FRAMEBUFFER99|
        DCD     &00000000                       ; Word r/- (referenced)

|DRAWTHICK|
; R0,R1 = x0,y0
; R2,R3 = x1,y1
; R4 = colour byte
        STR     R14,|RETFROMDRAWLINE|                 ; -> Word: &00000000, Function entry, (alters flags)
        BL      |ADJUSTCOLFORNIGHT|

        ; Translate coordinate origin to the middle of the screen
        LDR     R10,|MAXCOORDX2|                 ; -> Word: &0000013F
        ADD     R0,R0,R10,LSL #(CoordToScreenLog2-1)
        MOV     R0,R0,ASR #CoordToScreenLog2
        ADD     R2,R2,R10,LSL #(CoordToScreenLog2-1)
        MOV     R2,R2,ASR #CoordToScreenLog2

        LDR     R12,|MAXCOORDY2|                 ; -> Word: &000000F2
        ADD     R1,R1,R12,LSL #(CoordToScreenLog2-1)
        ADD     R3,R3,R12,LSL #(CoordToScreenLog2-1)
        MOV     R3,R3,ASR #CoordToScreenLog2
        MOV     R1,R1,ASR #CoordToScreenLog2

        CMP     R0,#0
        CMPLT   R2,#0
        BLT     |THICKLINEOFFSCREEN|

        CMP     R0,R10
        CMPGE   R2,R10
        BGE     |THICKLINEOFFSCREEN|

        CMP     R1,#0
        CMPLT   R3,#0
        BLT     |THICKLINEOFFSCREEN|

        CMP     R1,R12
        CMPGT   R3,R12
        BGT     |THICKLINEOFFSCREEN|

        CMP     R1,#0
        BLLT    |CLIPLINETOMINY|

        ; change to SUB R10,R10,#1 to fix x-clipping
        LDR     R12,|MAXCOORDY2| ; bug: redundant
        CMP     R1,R12
        BLGT    |CLIPLINETOMAXY|

        CMP     R0,#0
        BLLT    |CLIPLINETOMINX|

        CMP     R0,R10
        BLGT    |CLIPLINETOMAXX|

        SWAP    R0,R2,R6
        SWAP    R1,R3,R6

        CMP     R1,#0
        BLLT    |CLIPLINETOMINY|

        LDR     R12,|MAXCOORDY2|                 ; -> Word: &000000F2
        CMP     R1,R12
        BLGT    |CLIPLINETOMAXY|

        CMP     R0,#0
        BLLT    |CLIPLINETOMINX|

        CMP     R0,R10
        BLGT    |CLIPLINETOMAXX|

        CMP     R3,R1
        BLE     |L0000D914|

        SWAP    R0,R2,R5
        SWAP    R1,R3,R5

|L0000D914|
        SUBS    R7,R2,R0 ; r7 = x difference
        RSBMI   R9,R7,#0
        MOVPL   R9,R7 ; r9 = x difference magnitude

        SUBS    R8,R3,R1 ; r8 = y difference
        RSBMI   R10,R8,#0
        MOVPL   R10,R8 ; r10 = y difference magnitude

        CMP     R9,#0
        CMPEQ   R10,#0
        CMPEQ   R9,#0 ; bug: redundant
        BEQ     |DRAWZEROLENTHICKLINE|

        CMP     R9,R10 ; x difference magnitude < y difference magnitude
        BLT     |DRAWSTEEPTHICKLINE|

        STMFD   R13!,{R0-R4}
        MOV     R1,R9
        MOV     R8,R10,LSL #FixedPointOneLog2
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R12,R3
        LDMFD   R13!,{R0-R4}

        MOV     R1,R1,LSL #FixedPointOneLog2
        LDR     R11,|FRAMEBUFFER99|                 ; -> Word: &00000000
        MOV     R9,#WIDTH
        MVN     R5,#&64                         ; ="d" (100)
        MOV     R7,R1,ASR #FixedPointOneLog2
        CMP     R0,R2
        MVNGT   R14,#0
        MOVLE   R14,#1 ; choose x increment or decrement

        STR     R2,|SHALLOWTHICKLINEX|                  ; -> Word: &00000000

|DRAWSHALLOWTHICKLINELOOP1|
        ADD     R10,R11,R0
        MOV     R8,R7,LSL #RowStrideALog2
        ADD     R8,R8,R7,LSL #RowStrideBLog2
        ADD     R10,R10,R8

        STRB    R4,[R10,#0]
        STRB    R4,[R10,#1]
        STRB    R4,[R10,#RowStride]                  ; =5<<6
        STRB    R4,[R10,#(RowStride+1)]                  ; =321

        SUB     R1,R1,R12
        ADD     R0,R0,R14 ; increment or decrement x coord
        MOV     R7,R1,ASR #FixedPointOneLog2
        CMP     R7,R3
        BGT     |DRAWSHALLOWTHICKLINELOOP1|

        LDR     R3,|SHALLOWTHICKLINEX|                  ; -> Word: &00000000

|DRAWSHALLOWTHICKLINELOOP2|
        ADD     R10,R11,R0
        MOV     R8,R7,LSL #RowStrideALog2
        ADD     R8,R8,R7,LSL #RowStrideBLog2
        ADD     R10,R10,R8

        STRB    R4,[R10,#0]
        STRB    R4,[R10,#1]
        STRB    R4,[R10,#RowStride]                  ; =5<<6
        STRB    R4,[R10,#(RowStride+1)]                  ; =321

        SUB     R1,R1,R12
        ADD     R0,R0,R14 ; increment or decrement x coord
        MOV     R7,R1,ASR #FixedPointOneLog2
        CMN     R14,#1
        CMPGT   R0,R3
        CMPEQ   R3,R0
        BLE     |DRAWSHALLOWTHICKLINELOOP2|

        LDR     R14,|RETFROMDRAWLINE|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|SHALLOWTHICKLINEX|
        DCD     &00000000                       ; Word r/w (referenced)

|DRAWSTEEPTHICKLINE|
        CMP     R1,R3
        RSBGT   R8,R8,#0

        STMFD   R13!,{R0-R4}
        MOV     R1,R8
        MOV     R8,R7,LSL #FixedPointOneLog2
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R12,R3
        LDMFD   R13!,{R0-R4}

        MOV     R0,R0,LSL #FixedPointOneLog2
        LDR     R11,|FRAMEBUFFER99|                 ; -> Word: &00000000
        MOV     R9,#1
|DRAWSTEEPTHICKLINELOOP|
        ADD     R10,R11,R0,ASR #FixedPointOneLog2
        MOV     R8,R1,LSL #RowStrideALog2
        ADD     R8,R8,R1,LSL #RowStrideBLog2
        ADD     R10,R10,R8
        MOV     R5,R1,LSL #BytesPerAddressLog2 ; bug?

        STRB    R4,[R10,#0]
        STRB    R4,[R10,#1]
        STRB    R4,[R10,#RowStride]                  ; =5<<6
        STRB    R4,[R10,#(RowStride+1)]                  ; =321

        SUB     R1,R1,#1
        ADD     R0,R0,R12
        CMP     R1,R3
        BGT     |DRAWSTEEPTHICKLINELOOP|

        ADD     R10,R11,R0,ASR #FixedPointOneLog2
        MOV     R8,R1,LSL #RowStrideALog2
        ADD     R8,R8,R1,LSL #RowStrideBLog2
        ADD     R10,R10,R8

        STRB    R4,[R10,#0]
        STRB    R4,[R10,#1]
        STRB    R4,[R10,#RowStride]                  ; =5<<6
        STRB    R4,[R10,#(RowStride+1)]                  ; =321

|THICKLINEOFFSCREEN|
        LDR     R14,|RETFROMDRAWLINE|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|DRAWZEROLENTHICKLINE|
        ; r0 = x coord
        ; r1 = y coord
        LDR     R11,|FRAMEBUFFER99|                 ; -> Word: &00000000
        ADD     R10,R11,R0
        MOV     R8,R1,LSL #RowStrideALog2
        ADD     R8,R8,R1,LSL #RowStrideBLog2
        ADD     R10,R10,R8

        STRB    R4,[R10,#0]
        STRB    R4,[R10,#1]
        STRB    R4,[R10,#RowStride]                  ; =5<<6
        STRB    R4,[R10,#(RowStride+1)]                  ; =321

        LDR     R14,|RETFROMDRAWLINE|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|DRAWLINE|
; R0,R1 = screen x0,y0
; R2,R3 = screen x1,y1
; R4 = colour
        STR     R14,|RETFROMDRAWLINE|                 ; -> Word: &00000000, Function entry, (alters flags)
        BL      |ADJUSTCOLFORNIGHT|

        ; Translate coordinate origin to the middle of the screen
        LDR     R10,|MAXCOORDX2|                 ; -> Word: &0000013F
        ADD     R0,R0,R10,LSL #(CoordToScreenLog2-1)
        MOV     R0,R0,ASR #CoordToScreenLog2
        ADD     R2,R2,R10,LSL #(CoordToScreenLog2-1)
        MOV     R2,R2,ASR #CoordToScreenLog2

        LDR     R12,|MAXCOORDY2|                 ; -> Word: &000000F2
        ADD     R1,R1,R12,LSL #(CoordToScreenLog2-1)
        ADD     R3,R3,R12,LSL #(CoordToScreenLog2-1)
        MOV     R3,R3,ASR #CoordToScreenLog2
        MOV     R1,R1,ASR #CoordToScreenLog2

        CMP     R0,#0
        CMPLT   R2,#0
        BLT     |LINEOFFSCREEN| ; whole line is off left of screen

        CMP     R0,#WIDTH
        CMPGE   R2,R10
        BGE     |LINEOFFSCREEN| ; whole line is off right of screen

        CMP     R1,#0
        CMPLT   R3,#0
        BLT     |LINEOFFSCREEN| ; whole line is off top of screen

        CMP     R1,R12
        CMPGT   R3,R12
        BGT     |LINEOFFSCREEN| ; whole line is off bottom of screen

        CMP     R1,#0
        BLLT    |CLIPLINETOMINY|

        LDR     R12,|MAXCOORDY2|                 ; -> Word: &000000F2
        CMP     R1,R12
        BLGT    |CLIPLINETOMAXY|

        CMP     R0,#0
        BLLT    |CLIPLINETOMINX|

        CMP     R0,R10
        BLGT    |CLIPLINETOMAXX|

        SWAP    R0,R2,R6
        SWAP    R1,R3,R6

        CMP     R1,#0
        BLLT    |CLIPLINETOMINY|

        LDR     R12,|MAXCOORDY2|                 ; -> Word: &000000F2
        CMP     R1,R12
        BLGT    |CLIPLINETOMAXY|

        CMP     R0,#0
        BLLT    |CLIPLINETOMINX|

        CMP     R0,R10
        BLGT    |CLIPLINETOMAXX|

        CMP     R3,R1
        BLE     |L0000DB94|

        SWAP    R0,R2,R5
        SWAP    R1,R3,R5

|L0000DB94|
        SUBS    R7,R2,R0 ; r7 = x difference
        RSBMI   R9,R7,#0
        MOVPL   R9,R7 ; r9 = x difference magnitude

        SUBS    R8,R3,R1 ; r8 = y difference
        RSBMI   R10,R8,#0
        MOVPL   R10,R8 ; r10 = y difference magnitude

        CMP     R9,#0
        CMPEQ   R10,#0
        CMPEQ   R9,#0 ; bug: redundant
        BEQ     |DRAWZEROLENLINE|

        CMP     R9,R10 ; x difference magnitude < y difference magnitude
        BLT     |DRAWSTEEPLINE|

        ; Draw a shallow (or horizontal) line
        STMFD   R13!,{R0-R4}
        MOV     R1,R9
        MOV     R8,R10,LSL #FixedPointOneLog2
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R12,R3
        LDMFD   R13!,{R0-R4}

        MOV     R1,R1,LSL #FixedPointOneLog2
        LDR     R11,|FRAMEBUFFER99|                 ; -> Word: &00000000
        MOV     R9,#WIDTH ; bug: redundant
        MVN     R5,#&64 ; bug: redundant         ; ="d" (100)
        MOV     R7,R1,ASR #FixedPointOneLog2
        CMP     R0,R2
        MVNGT   R14,#0
        MOVLE   R14,#1 ; choose x increment or decrement

        STR     R2,|SHALLOWLINEX|                  ; -> Word: &00000000

|DRAWSHALLOWLINELOOP1|
        ADD     R10,R11,R0
        MOV     R8,R7,LSL #RowStrideALog2
        ADD     R8,R8,R7,LSL #RowStrideBLog2
        ADD     R10,R10,R8
        STRB    R4,[R10,#0] ; draw one pixel of the line

        SUB     R1,R1,R12
        ADD     R0,R0,R14 ; increment or decrement x coord
        MOV     R7,R1,ASR #FixedPointOneLog2
        CMP     R7,R3
        BGT     |DRAWSHALLOWLINELOOP1|

        LDR     R3,|SHALLOWLINEX|                  ; -> Word: &00000000

|DRAWSHALLOWLINELOOP2|
        ADD     R10,R11,R0
        MOV     R8,R7,LSL #RowStrideALog2
        ADD     R8,R8,R7,LSL #RowStrideBLog2
        ADD     R10,R10,R8
        STRB    R4,[R10,#0] ; draw one pixel of the line

        SUB     R1,R1,R12
        ADD     R0,R0,R14
        MOV     R7,R1,ASR #FixedPointOneLog2
        CMN     R14,#1
        CMPGT   R0,R3
        CMPEQ   R3,R0
        BLE     |DRAWSHALLOWLINELOOP2|

        LDR     R14,|RETFROMDRAWLINE|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|SHALLOWLINEX|
        DCD     &00000000                       ; Word r/w (referenced)

|DRAWSTEEPLINE|
        ; Draw a steep (or vertical) line
        ; r8 = y difference
        CMP     R1,R3
        RSBGT   R8,R8,#0

        STMFD   R13!,{R0-R4}
        MOV     R1,R8
        MOV     R8,R7,LSL #FixedPointOneLog2
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R12,R3
        LDMFD   R13!,{R0-R4}

        MOV     R0,R0,LSL #FixedPointOneLog2
        LDR     R11,|FRAMEBUFFER99|                 ; -> Word: &00000000
        MOV     R9,#1 ; bug: redundant
|DRAWSTEEPLINELOOP|
        ADD     R10,R11,R0,ASR #FixedPointOneLog2
        MOV     R8,R1,LSL #RowStrideALog2
        ADD     R8,R8,R1,LSL #RowStrideBLog2
        ADD     R10,R10,R8
        MOV     R5,R1,LSL #BytesPerAddressLog2 ; bug: redundant
        STRB    R4,[R10,#0] ; draw one pixel of the line

        SUB     R1,R1,#1
        ADD     R0,R0,R12
        CMP     R1,R3
        BGT     |DRAWSTEEPLINELOOP|

        ADD     R10,R11,R0,ASR #FixedPointOneLog2
        MOV     R8,R1,LSL #RowStrideALog2
        ADD     R8,R8,R1,LSL #RowStrideBLog2
        ADD     R10,R10,R8
        STRB    R4,[R10,#0] ; draw one pixel of the line

|LINEOFFSCREEN|
        LDR     R14,|RETFROMDRAWLINE|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|DRAWZEROLENLINE|
        ; r0 = x coord
        ; r1 = y coord
        LDR     R11,|FRAMEBUFFER99|                 ; -> Word: &00000000
        ADD     R10,R11,R0
        MOV     R8,R1,LSL #RowStrideALog2
        ADD     R8,R8,R1,LSL #RowStrideBLog2
        ADD     R10,R10,R8
        STRB    R4,[R10,#0]
        LDR     R14,|RETFROMDRAWLINE|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|CLIPLINETOMINX|
        ; r0 = x coord to clip
        MOV     R11,R14                         ; Function entry
        CMP     R2,#0
        BLT     |THICKLINEOFFSCREEN|

        STMFD   R13!,{R0-R4}
        SUB     R8,R2,#0
        MOV     R8,R8,LSL #FixedPointOneLog2
        SUB     R1,R2,R0
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R5,R3

        LDMFD   R13!,{R0-R4}
        MOV     R0,#0
        SUB     R6,R3,R1
        MUL     R7,R5,R6
        MOV     R7,R7,ASR #FixedPointOneLog2
        SUB     R1,R3,R7
        MOV     PC,R11                          ; Ends, Dynamic branch

|CLIPLINETOMAXX|
        ; r0 = x coord to clip
        ; r10 = max x coord
        MOV     R11,R14                         ; Function entry
        CMP     R2,R10
        BGT     |THICKLINEOFFSCREEN| ; x1 > maxx

        STMFD   R13!,{R0-R4}
        RSB     R8,R2,R10 ; maxx - x1
        MOV     R8,R8,LSL #FixedPointOneLog2
        SUB     R1,R0,R2 ; x0 - x1
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R5,R3 ; fraction of line on screen = (maxx - x1) / (x0 - x1)

        LDMFD   R13!,{R0-R4}
        MOV     R0,R10 ; x0 = maxx
        SUB     R6,R3,R1 ; y1 - y0
        MUL     R7,R5,R6 ; y intercept = fraction of line on screen * (y1 - y0)
        MOV     R7,R7,ASR #FixedPointOneLog2
        SUB     R1,R3,R7 ; y0 = y1 - y intercept
        MOV     PC,R11                          ; Ends, Dynamic branch

|CLIPLINETOMINY|
        ; r1 = y coord to clip
        MOV     R11,R14                         ; Function entry, (alters flags)
        CMP     R3,#0
        BLT     |THICKLINEOFFSCREEN|

        STMFD   R13!,{R0-R4}
        SUB     R8,R3,#0
        MOV     R8,R8,LSL #FixedPointOneLog2
        SUB     R1,R3,R1
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R5,R3

        LDMFD   R13!,{R0-R4}
        MOV     R1,#0
        SUB     R6,R2,R0
        MUL     R7,R5,R6
        MOV     R7,R7,ASR #FixedPointOneLog2
        SUB     R0,R2,R7
        MOV     PC,R11                          ; Ends, Dynamic branch

|CLIPLINETOMAXY|
        ; r1 = y coord to clip
        ; r12 = max y coord
        MOV     R11,R14                         ; Function entry
        CMP     R3,R12
        BGT     |THICKLINEOFFSCREEN|

        STMFD   R13!,{R0-R4}
        RSB     R8,R3,R12
        MOV     R8,R8,LSL #FixedPointOneLog2
        SUB     R1,R1,R3
        BL      |DIVIDE| ; returns quotient in R3
        MOV     R5,R3

        LDMFD   R13!,{R0-R4}
        LDR     R1,|MAXCOORDY2|                  ; -> Word: &000000F2
        SUB     R6,R2,R0
        MUL     R7,R5,R6
        MOV     R7,R7,ASR #FixedPointOneLog2
        SUB     R0,R2,R7
        MOV     PC,R11                          ; Ends, Dynamic branch

|HONOLULUBLUE|
        MAKEFILL HonoluluBlue

|PROTATIONMATRIXB|
        DCD     |ROTATIONMATRIXB|
|PROTATIONMATRIXC|
        DCD     |ROTATIONMATRIXC|
|PYANGLE|
        DCD     |YANGLE|
|RETURNFROMDRAWSKY|
        DCD     &00000000                       ; Word r/w (referenced)
|SRCCOORDSPLUS16C|
        DCD     (MemSrcCoords+&10)                       ; Word r/- (referenced)
|P2ISNIGHTMISSION|
        DCD     |ISNIGHTMISSION|
|P2THUNDERCOUNTDOWN10|
        DCD     |THUNDERCOUNTDOWN10|

|DRAWSKY|
        LDR     R0,|PYANGLE|                  ; -> Word: &0001D350, Function entry, (alters flags)
        LDR     R0,[R0,#0]
        ABSDIFF R0,R0,#QuarterTurn                   ; =&5A0
        CMP     R0,#&C8                         ; ="" (200)
        MOVLT   PC,R14                          ; Function exit if LT

        STR     R14,|RETURNFROMDRAWSKY|                 ; -> Word: &00000000
        LDR     R14,|PROTATIONMATRIXB|                 ; -> Word: &0001D32C
        MOV     R3,#3
        MVN     R4,#&32000                      ; =&32000
        LDR     R0,|SRCCOORDSPLUS16C|                  ; -> Word: (MemSrcCoords+&10)
|L0000DE78|
        CMP     R3,#1
        MVNEQ   R4,#&32000                      ; =&32000
        MOV     R5,R4
        STR     R5,[R0,#0]
        ADD     R4,R4,#&19,18                   ; =&64000
        MOV     R6,#0
        CMP     R3,#2
        MOVGE   R5,#&19,20                      ; =&19000
        MVNLT   R5,#&19,20                      ; =&19000
        LDMIA   R14!,{R9-R12}
        MUL     R7,R5,R12
        MOV     R7,R7,ASR #12
        MUL     R8,R6,R11
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#4]
        MUL     R7,R6,R9
        MOV     R7,R7,ASR #12
        MUL     R8,R5,R10
        ADD     R6,R7,R8,ASR #12
        LDR     R5,[R0,#0]
        LDMIA   R14,{R9-R12}
        MUL     R7,R6,R9
        MOV     R7,R7,ASR #12
        MUL     R8,R5,R10
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#8]
        MUL     R7,R5,R12
        MOV     R7,R7,ASR #12
        MUL     R8,R6,R11
        ADD     R8,R7,R8,ASR #12
        STR     R8,[R0,#0]
        ADD     R0,R0,#&0C                      ; =12
        SUB     R14,R14,#&10                    ; =16
        SUBS    R3,R3,#1
        BPL     |L0000DE78|

        LDR     R12,|SRCCOORDSPLUS16C|                 ; -> Word: (MemSrcCoords+&10)
        MOV     R8,R12

        LDMIA   R12!,{R0-R2}
        CMP     R1,#0
        ADDLT   R12,R12,#&0C                    ; =12
        LDMLTIA R12!,{R0-R2}
        MOVLT   R7,#&19,20                      ; =&19000
        MVNGE   R7,#&19,20                      ; =&19000
        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        STMIA   R8!,{R0,R2} ; 1st coord

        LDMIA   R12!,{R0-R2}
        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        STMIA   R8!,{R0,R2} ; 2nd coord

        LDR     R14,|PROTATIONMATRIXC|                 ; -> Word: &0001D33C
        LDMIA   R14,{R9-R12}

        MOV     R5,R7
        MOV     R6,#0

        MUL     R7,R6,R9
        MOV     R7,R7,ASR #12

        MUL     R4,R5,R10
        ADD     R4,R7,R4,ASR #12

        MUL     R7,R5,R12
        MOV     R7,R7,ASR #12

        MUL     R5,R6,R11
        ADD     R5,R7,R5,ASR #12

        MVN     R4,R4
        STMIA   R8,{R4,R5} ; 3rd coord

        SUB     R0,R8,#&10 ; polygon coordinates
        MOV     R1,#HonoluluBlue
        MOV     R2,#PolygonStyleAzureOutline
        MOV     R12,#3 ; triangle

        LDR     R8,|P2ISNIGHTMISSION|                  ; -> Word: &0001E61C
        LDR     R7,[R8,#4] ; get |LIGHTNINGFLASH|
        CMP     R7,#1
        MOVEQ   R1,#HonoluluBlue2

        LDR     R7,[R8,#0]
        CMP     R7,#0
        MOVNE   R2,#PolygonStyleNoOutline

        MOV     R3,#DrawPolygonMayDarken
        BL      |DRAWPOLYGON|

        LDR     R14,|RETURNFROMDRAWSKY|                 ; -> Word: &00000000
        MOV     PC,R14                          ; Function exit, Ends

|COSINE10|
        DCD     MemCosine                       ; Word r/- (referenced)
|SINE10|
        DCD     MemSine                       ; Word r/- (referenced)

|SERVICELIGHTNING|
        LDR     R8,|P2THUNDERCOUNTDOWN10|                  ; -> Word: &0001AF88, Function entry, (alters flags)
        LDR     R8,[R8,#0]
        MOV     R7,#0
        CMP     R8,#7
        MOVGT   R7,#1
        TST     R8,#1
        MOVNE   R7,#1

        LDR     R8,|P2ISNIGHTMISSION|                  ; -> Word: &0001E61C
        STR     R7,[R8,#4] ; get |LIGHTNINGFLASH|

        MOV     PC,R14                          ; Function exit, Ends

|ROTATE2DCOORD|
        ; R6 = x coord
        ; R7 = y coord
        ; R11 = angle
        CMP     R11,#FullRotation                     ; =&1680, Function entry, (alters flags)
        SUBGT   R11,R11,#FullRotation                 ; =&1680

        LDR     R8,|COSINE10|                  ; -> Word: MemCosine

        LDR     R12,[R8,R11] ; get cosine(a)
        MUL     R5,R12,R7
        MOV     R5,R5,ASR #12 ; cosine(a) * y

        ; The x coordinate is 90 degrees from the y coordinate
        ; Note that sine(a+90) = cosine(a)
        ; and cosine(a+90) = -sine(a)
        ADD     R11,R11,#QuarterTurn                 ; =&5A0

        LDR     R12,[R8,R11] ; get cosine(a+90)=-sine(a)
        MUL     R9,R12,R6
        MOV     R9,R9,ASR #12 ; -sine(a) * x
        ADD     R10,R9,R5 ; (-sine(a) * x) + (cosine(a) * y)

        LDR     R8,|SINE10|                  ; -> Word: MemSine

        LDR     R12,[R8,R11] ; get sine(a+90)=cosine(a)
        MUL     R5,R12,R6
        MOV     R5,R5,ASR #12 ; cosine(a) * x

        SUB     R11,R11,#QuarterTurn                 ; =&5A0

        LDR     R12,[R8,R11] ; get sine(a)
        MUL     R9,R12,R7
        MOV     R9,R9,ASR #12 ; sine(a) * y
        ADD     R6,R9,R5 ; (sine(a) * y) + (cosine(a) * x)

        MOV     R7,R10 ; (-sine(a) * x) + (cosine(a) * y)

        MOV     PC,R14                          ; Function exit, Ends

|DIVDATA3|
        DCD     &00077338                       ; Word r/- (referenced)

|L0000E038| ; Dead code
        SUB     R13,R13,#&20                    ;~~ =" " (32)
        STMFD   R13!,{R1,R3-R12,R14}            ;~

        CMP     R1,#&1E                         ;~ =30
        MOVLT   R1,#&1E                         ;~ =30

        MOV     R11,R0                          ;~
        MOV     R12,R2                          ;~

        CMP     R1,#&C8                         ;~ ="" (200)
        LDRLT   R8,|DEADDIVIDENDA|                  ;~ -> Word: &0000927C
        LDRGE   R8,|DEADDIVIDENDB|                  ;~ -> Word: &000249F0
        MOVLT   R9,#6                           ;~
        MOVGE   R9,#8                           ;~

        CMP     R1,#&01,22                      ;~ =&400
        LDRGE   R8,|DEADDIVIDENDC|                  ;~ -> Word: &00124F80
        MOVGE   R9,#&0B                         ;~ =11

        CMP     R1,#&0A,22                      ;~ =&2800
        LDRGE   R8,|DEADDIVIDENDD|                  ;~ -> Word: &00927C00
        MOVGE   R9,#&0E                         ;~ =14

        BL      |DIVIDE| ; returns quotient in R3                     ;~

        MUL     R2,R11,R3                       ;~
        MOV     R0,R2,ASR R9                    ;~

        MUL     R4,R12,R3                       ;~
        MOV     R2,R4,ASR R9                    ;~

        LDMFD   R13!,{R1,R3-R12,R14}            ;~
        ADD     R13,R13,#&20                    ;~ =" " (32)
        MOV     PC,R14                          ;~ Function exit, Ends

|DEADDIVIDENDA|
        DCD     &0000927C                       ;~ Word r/- (referenced)
|DEADDIVIDENDB|
        DCD     &000249F0                       ;~ Word r/- (referenced)
|DEADDIVIDENDC|
        DCD     &00124F80                       ;~ Word r/- (referenced)
|DEADDIVIDENDD|
        DCD     &00927C00                       ;~ Word r/- (referenced)

|PROJECT3D| ; In R0-R2, out R0,R2
        ; Divide x,z by y
        ; R0,R1,R2 = coords x,y,z
        ; returns R0 = x/y R2 = z/y
        CMP     R1,#&0A,22                      ; =&2800, Function entry, (alters flags)
        BGE     |PROJECT3DFAR|
        MOV     R4,R1,LSL #BytesPerWordLog2
        LDR     R3,|DIVDATA3|                  ; -> Word: &00077338
        LDR     R3,[R3,R4]
        CMP     R1,#&C8                         ; ="" (200)
        MOVLT   R5,#6
        MOVGE   R5,#8
        CMP     R1,#&01,22                      ; =&400
        MOVGE   R5,#&0B                         ; =11
        MUL     R6,R0,R3
        MOV     R0,R6,ASR R5
        MUL     R6,R2,R3
        MOV     R2,R6,ASR R5
        MOV     PC,R14                          ; Function exit, Ends
|PROJECT3DFAR|
        ; y > 10240, y -= 10240
        SUB     R1,R1,#&0A,22                   ; =&2800
        MOV     R1,R1,ASR #4
        BIC     R1,R1,#WordAlignMask
        ADD     R4,R1,#&0A,20                   ; =&A000
        LDR     R3,|DIVDATA3|                  ; -> Word: &00077338
        LDR     R3,[R3,R4]
        MUL     R6,R0,R3
        MOV     R0,R6,ASR #14
        MUL     R6,R2,R3
        MOV     R2,R6,ASR #14
        MOV     PC,R14                          ; Function exit, Ends

|PROJECT3DB| ; In R0-R2,R8 out R0,R2
        ; Divide x,z by y
        ; R0,R1,R2 = coords x,y,z
        ; R8 = divdata
        ; returns R0 = x/y R2 = z/y
        CMP     R1,#&0A,22                      ; =&2800, Function entry, (alters flags)
        BGE     |PROJECT3DBFAR|
        MOV     R4,R1,LSL #BytesPerWordLog2
        LDR     R3,[R8,R4]
        CMP     R1,#&C8                         ; ="" (200)
        MOVLT   R5,#6
        MOVGE   R5,#8
        CMP     R1,#&01,22                      ; =&400
        MOVGE   R5,#&0B                         ; =11
        MUL     R6,R0,R3
        MOV     R0,R6,ASR R5
        MUL     R6,R2,R3
        MOV     R2,R6,ASR R5
        MOV     PC,R14                          ; Function exit, Ends
|PROJECT3DBFAR|
        SUB     R1,R1,#&0A,22                   ; =&2800
        MOV     R1,R1,ASR #4
        BIC     R1,R1,#WordAlignMask
        ADD     R4,R1,#&0A,20                   ; =&A000
        LDR     R3,[R8,R4]
        MUL     R6,R0,R3
        MOV     R0,R6,ASR #14
        MUL     R6,R2,R3
        MOV     R2,R6,ASR #14
        MOV     PC,R14                          ; Function exit, Ends

|DIVIDE| ; returns quotient in R3
        ; R3 = R8/R1
        ; R1 = divisor
        ; R8 = dividend
        ; R3 = quotient
        MOV     R2,#1                           ; Function entry, (alters flags)
        ANDS    R4,R1,#&02,2                    ; =&80000000
        RSBMI   R1,R1,#0
        EOR     R5,R4,R8
        CMP     R8,#0
        RSBMI   R8,R8,#0
        CMP     R1,#0
        MVNEQ   R3,#&02,2                       ; =&80000000
        BEQ     |DIVIDEEND|

count SETA 0
        WHILE count < 33

        CMP     R1,R8
        MOVCC   R1,R1,LSL #1
        MOVCC   R2,R2,LSL #1
        BCS     |DIVIDEEXIT1|

count SETA count + 1
        WEND

|DIVIDEEXIT1|

        MOV     R3,#0

count SETA 0
        WHILE count < 33

        CMP     R8,R1
        SUBCS   R8,R8,R1
        ADDCS   R3,R3,R2
        MOVS    R2,R2,LSR #1
        MOVNE   R1,R1,LSR #1
        BEQ     |DIVIDEEND|

count SETA count + 1
        WEND

|DIVIDEEND|
        CMP     R5,#0
        RSBMI   R3,R3,#0
        MOV     PC,R14                          ; Function exit, Ends

|DRAWSPECIALLINE|
        ; r2 = special vertex no. (>= 253)
        LDR     R0,|GRAPHICSDETAILCOPY|                  ; -> Word: &00000000, Function entry, (alters flags)
        CMP     R0,#9
        MOVEQ   R2,#0
        MOVEQ   PC,R14                          ; Function exit if EQ
        CMP     R8,#2
        BEQ     |DRAWNEXTPOLYGON|

        CMP     R2,#VertexThinWhiteLine16Dash                         ; ="" (254)
        BEQ     |THINWHITELINE16DASH|

        CMP     R2,#VertexThinWhiteLine8Dash                         ; ="" (253)
        BEQ     |THINWHITELINE8DASH|

        ; Draw a thick white line with 32 dashes
        LDR     R0,|LINECOORDS4|                  ; -> Word: MemLineCoords
        LDMIA   R0,{R7-R12}
        ; R7-R9   = v0 {x0,y0,z0}
        ; R10-R12 = v1 {x1,y1,z1}
        CMP     R8,R11
        BGT     |NOSWAPLINECOORDS| ; y0 > y1

        SWAP    R7,R10,R4 ; swap v0,v1
        SWAP    R8,R11,R4
        SWAP    R9,R12,R4

        ; Compute vector from one end of the line to the other
        SUB     R10,R10,R7
        SUB     R11,R11,R8
        SUB     R12,R12,R9 ; x0-x1, y0-y1 (-ve), z0-z1 vector

        ; If starting from the opposite end of the line then
        ; begin at a gap instead of a dash
        ADD     R7,R7,R10,ASR #6
        ADD     R8,R8,R11,ASR #6
        ADD     R9,R9,R12,ASR #6 ; add on vector/64
        B       |SWAPPEDLINECOORDS|                     ; Ends

|NOSWAPLINECOORDS|
        ; Compute vector from one end of the line to the other
        SUB     R10,R10,R7
        SUB     R11,R11,R8
        SUB     R12,R12,R9 ; x1-x0, y1-y0 (-ve), z1-z0 vector

|SWAPPEDLINECOORDS|
        ; Scale the starting coordinates up to 32 times the length
        ; of the vector from one end of the line to the other so
        ; we can use the latter to move between dashes
        MOV     R7,R7,LSL #5
        MOV     R8,R8,LSL #5
        MOV     R9,R9,LSL #5 ; x*32, y*32, z*32
        MOV     R14,#&1F                        ; =31

|DASHEDLINELOOP32|
        CMP     R8,#LineClipDist
        BLT     |DRAWNEXTPOLYGON|
        STR     R14,|DRAWLINECOUNTER|                 ; -> Word: &00000000

        ; Scale the coordinates back down from 32 times the length
        ; of the vector
        MOV     R0,R7,ASR #5
        MOV     R1,R8,ASR #5
        MOV     R2,R9,ASR #5 ; x/32, y/32, z/32
        BL      |PROJECT3D| ; In R0-R2, out R0,R2 ; outputs x0/y0, z0/y0
        STMDB   R13,{R0,R2} ; x0/y0, z0/y0

        MOV     R1,R8,ASR #5
        ADD     R1,R1,R11,ASR #6 ; y/32 + dy/64
        CMP     R1,#8
        BLT     |DRAWNEXTPOLYGON| ; too close?

        MOV     R0,R7,ASR #5 ; x/32
        MOV     R2,R9,ASR #5 ; z/32
        ADD     R0,R0,R10,ASR #6 ; x/32 + dx/64
        ADD     R2,R2,R12,ASR #6 ; z/32 + dz/64
        BL      |PROJECT3D| ; In R0-R2, out R0,R2 ; outputs x1/y1, z1/y1

        CMP     R1,#MaxThickWhiteDashedLineDist ; bug: R1 is corrupted
        MOV     R1,R2 ; z1/y1
        LDMDB   R13,{R2,R3} ; x0/y0, z0/y0
        STMFD   R13!,{R7-R12}
        BGT     |DRAWTHINLINE|

        MOV     R4,#White                         ; ="" (255)
        BL      |DRAWTHICK| ; In R0-R3 coords, R4 colour
        B       |NEXTDASHEDLINE32|                     ; Ends

|DRAWTHINLINE|
        MOV     R4,#White                         ; ="" (255)
        BL      |DRAWLINE|
|NEXTDASHEDLINE32|
        LDMFD   R13!,{R7-R12}
        LDR     R14,|DRAWLINECOUNTER|                 ; -> Word: &00000000

        ADD     R7,R7,R10 ; x += dx
        ADD     R8,R8,R11 ; y += dy
        ADD     R9,R9,R12 ; z += dz
        SUBS    R14,R14,#1
        BPL     |DASHEDLINELOOP32|
        B       |DRAWNEXTPOLYGON|                     ; Ends

|DRAWLINECOUNTER|
        DCD     &00000000                       ; Word r/w (referenced)
|LINECOORDS4|
        DCD     MemLineCoords                       ; Word r/- (referenced)
|GRAPHICSDETAILCOPY|
        DCD     &00000000                       ; Word r/- (referenced)

|THINWHITELINE16DASH|
        ; Draw a thin white line with 16 dashes
        LDR     R0,|LINECOORDS4|                  ; -> Word: MemLineCoords
        LDMIA   R0,{R7-R12}
        ; R7-R9   = v0 {x0,y0,z0}
        ; R10-R12 = v1 {x1,y1,z1}
        CMP     R8,R11
        BGT     |L0000E84C| ; y0 > y1

        SWAP    R7,R10,R4 ; swap v0,v1
        SWAP    R8,R11,R4
        SWAP    R9,R12,R4

        SUB     R10,R10,R7 ; v1 -= v0
        SUB     R11,R11,R8
        SUB     R12,R12,R9

        ; If starting from the opposite end of the line then
        ; begin at a gap instead of a dash
        ADD     R7,R7,R10,ASR #5
        ADD     R8,R8,R11,ASR #5
        ADD     R9,R9,R12,ASR #5 ; add on vector/32

        B       |L0000E858|                     ; Ends
|L0000E84C|
        SUB     R10,R10,R7
        SUB     R11,R11,R8
        SUB     R12,R12,R9
|L0000E858|
        MOV     R7,R7,LSL #4
        MOV     R8,R8,LSL #4
        MOV     R9,R9,LSL #4 ; x*16, y*16, z*16
        MOV     R14,#&0F                        ; =15
|L0000E868|
        CMP     R8,#LineClipDist2
        BLT     |DRAWNEXTPOLYGON|

        STR     R14,|DRAWLINECOUNTER|                 ; -> Word: &00000000
        MOV     R0,R7,ASR #4
        MOV     R1,R8,ASR #4
        MOV     R2,R9,ASR #4 ; x/16, y/16, z/16
        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        STMDB   R13,{R0,R2}

        MOV     R1,R8,ASR #4
        ADD     R1,R1,R11,ASR #5
        CMP     R1,#8
        BLT     |DRAWNEXTPOLYGON|

        MOV     R0,R7,ASR #4
        MOV     R2,R9,ASR #4
        ADD     R0,R0,R10,ASR #5
        ADD     R2,R2,R12,ASR #5
        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        MOV     R1,R2
        LDMDB   R13,{R2,R3}

        STMFD   R13!,{R7-R12}
        MOV     R4,#White                         ; ="" (255)
        BL      |DRAWLINE|
        LDMFD   R13!,{R7-R12}

        LDR     R14,|DRAWLINECOUNTER|                 ; -> Word: &00000000

        ADD     R7,R7,R10
        ADD     R8,R8,R11
        ADD     R9,R9,R12

        SUBS    R14,R14,#1
        BPL     |L0000E868|

        B       |DRAWNEXTPOLYGON|                     ; Ends

|SPECIALORANGEPOINTS|
        LDR     R0,|LINECOORDS4|                  ; -> Word: MemLineCoords
        LDMIA   R0,{R7-R12}
        ; R7-R9   = v0 {x0,y0,z0}
        ; R10-R12 = v1 {x1,y1,z1}
        ; v2 seems to be ignored

        CMP     R8,R11
        BGT     |L0000E930|

        SWAP    R7,R10,R4 ; swap v0,v1
        SWAP    R8,R11,R4
        SWAP    R9,R12,R4

        SUB     R10,R10,R7
        SUB     R11,R11,R8
        SUB     R12,R12,R9 ; v1 -= v0

        ADD     R7,R7,R10,ASR #6
        ADD     R8,R8,R11,ASR #6
        ADD     R9,R9,R12,ASR #6 ; v0 += v1 / 64

        B       |L0000E93C|                     ; Ends

|L0000E930|
        SUB     R10,R10,R7
        SUB     R11,R11,R8
        SUB     R12,R12,R9 ; v1 -= v0

|L0000E93C|
        MOV     R7,R7,LSL #5
        MOV     R8,R8,LSL #5
        MOV     R9,R9,LSL #5 ; v0 *= 32
        MOV     R14,#&1F                        ; =31
|PLOTPOINTLOOP|
        CMP     R8,#PointClipDist                     ; ="" (150)
        BLT     |DRAWNEXTPOLYGON|

        STR     R14,|DRAWLINECOUNTER|                 ; -> Word: &00000000

        MOV     R0,R7,ASR #5
        MOV     R1,R8,ASR #5
        MOV     R2,R9,ASR #5 ; project v0 / 32

        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        STMDB   R13,{R0,R2} ; WTF?

        MOV     R1,R8,ASR #5
        ADD     R1,R1,R11,ASR #6 ; y0/32 + y1/64
        CMP     R1,#8
        BLT     |DRAWNEXTPOLYGON|

        MOV     R0,R7,ASR #5
        MOV     R2,R9,ASR #5
        ADD     R0,R0,R10,ASR #6 ; x0/32 + x1/64
        ADD     R2,R2,R12,ASR #6 ; z0/32 + z1/64
        ; project v0/32 + v1/64
        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        MOV     R1,R2 ; y coord

        LDMDB   R13,{R2,R3} ; WTF?

        STMFD   R13!,{R7-R12}
        MOV     R4,#Orange
        BL      |PLOTPOINT| ; Input R0,R1 (coords), R4 (colour)
        LDMFD   R13!,{R7-R12}

        LDR     R14,|DRAWLINECOUNTER|                 ; -> Word: &00000000
        ADD     R7,R7,R10
        ADD     R8,R8,R11
        ADD     R9,R9,R12 ; v0 += v1
        SUBS    R14,R14,#1
        BPL     |PLOTPOINTLOOP|

        B       |DRAWNEXTPOLYGON|                     ; Ends

|SPECIALBLACKZIGZAG|
        LDR     R0,|LINECOORDS4|                  ; -> Word: MemLineCoords
        LDMIA   R0,{R4-R12}
        ; R4-R6   = v0 {x0,y0,z0}
        ; R7-R9   = v1 {x1,y1,z1}
        ; R10-R12 = v2 {x2,y2,z2}

        SUB     R4,R4,R7
        SUB     R5,R5,R8
        SUB     R6,R6,R9 ; v0 -= v1

        STMFD   R13!,{R4-R6}
        CMP     R8,R11
        BGT     |L0000EA08|

        SWAP    R7,R10,R4 ; swap v1,v2
        SWAP    R8,R11,R4
        SWAP    R9,R12,R4

|L0000EA08|
        SUB     R10,R10,R7 ; v2 -= v1
        SUB     R11,R11,R8
        SUB     R12,R12,R9

        MOV     R7,R7,LSL #4 ; v1 *= 16
        MOV     R8,R8,LSL #4
        MOV     R9,R9,LSL #4

        MOV     R14,#&0F                        ; =15
|L0000EA24|
        CMP     R8,#LineClipDist2
        BLT     |ADJUSTSTACKANDDONEXT2|
        STR     R14,|DRAWLINECOUNTER|                 ; -> Word: &00000000

        MOV     R0,R7,ASR #4
        MOV     R1,R8,ASR #4
        MOV     R2,R9,ASR #4 ; project v1 (scaled back to 1:1)
        BL      |PROJECT3D| ; In R0-R2, out R0,R2

        LDMFD   R13,{R4-R6} ; get v0
        STMDB   R13,{R0,R2} ; store screen x1,y1
        MOV     R1,R8,ASR #4
        ADD     R1,R1,R11,ASR #4
        ADD     R1,R1,R5
        CMP     R1,#8
        BLT     |ADJUSTSTACKANDDONEXT2|
        MOV     R0,R7,ASR #4
        MOV     R2,R9,ASR #4
        ADD     R0,R0,R10,ASR #4
        ADD     R2,R2,R12,ASR #4
        ADD     R0,R0,R4
        ADD     R2,R2,R6 ; project v1 (scaled back to 1:1) + v2/16 + v0
        BL      |PROJECT3D| ; In R0-R2, out R0,R2

        MOV     R1,R2 ; screen y0 coord
        LDMDB   R13,{R2,R3} ; get screen x1,y1
        STMFD   R13!,{R7-R12}
        MOV     R4,#Black
        BL      |DRAWLINE|
        LDMFD   R13!,{R7-R12}
        LDR     R14,|DRAWLINECOUNTER|                 ; -> Word: &00000000

        ; 16 times we add on v2, which is 1:16th scale compared to v1
        ADD     R7,R7,R10 ; v1*16 += v2
        ADD     R8,R8,R11
        ADD     R9,R9,R12

        LDMFD   R13,{R4-R6} ; get v0

        ADD     R7,R7,R4,LSL #4
        ADD     R8,R8,R5,LSL #4
        ADD     R9,R9,R6,LSL #4 ; v1*16 += v0*16

        RSB     R4,R4,#0
        RSB     R5,R5,#0
        RSB     R6,R6,#0 ; v0 = -v0

        STMEA   R13,{R4-R6} ; store negated v0

        SUBS    R14,R14,#1
        BPL     |L0000EA24|
|ADJUSTSTACKANDDONEXT2|
        ADD     R13,R13,#&0C                    ; =12
        B       |DRAWNEXTPOLYGON|                     ; Ends

|SPECIALPERULINES|
        LDR     R0,|LINECOORDS4|                  ; -> Word: MemLineCoords
        LDMIA   R0,{R4-R12}
        ; R4-R6   = v0 {x0,y0,z0}
        ; R7-R9   = v1 {x1,y1,z1}
        ; R10-R12 = v2 {x2,y2,z2}

        SUB     R4,R4,R7
        SUB     R5,R5,R8
        SUB     R6,R6,R9 ; v0 -= v1

        STMFD   R13!,{R4-R6} ; store v0
        CMP     R8,R11
        BGT     |L0000EB14| ; y1 > y2

        SWAP    R7,R10,R4 ; swap v1,v2
        SWAP    R8,R11,R4
        SWAP    R9,R12,R4

|L0000EB14|
        SUB     R10,R10,R7 ; v2 -= v1
        SUB     R11,R11,R8
        SUB     R12,R12,R9

        MOV     R7,R7,LSL #6 ; v1 *= 64
        MOV     R8,R8,LSL #6
        MOV     R9,R9,LSL #6

        MOV     R14,#&3F                        ; ="?" (63)
|DRAWPERULINELOOP|
        CMP     R8,#LineClipDist3
        BLT     |ADJUSTSTACKANDDONEXT2|
        STR     R14,|DRAWLINECOUNTER|                 ; -> Word: &00000000

        MOV     R0,R7,ASR #6
        MOV     R1,R8,ASR #6
        MOV     R2,R9,ASR #6 ; project v1 (scaled back to 1:1)

        BL      |PROJECT3D| ; In R0-R2, out R0,R2

        LDMFD   R13,{R4-R6} ; get v0
        STMDB   R13,{R0-R2} ; store screen x1,rubbish,y1
        MOV     R1,R8,ASR #6 ; v1/64
        ADD     R1,R1,R5 ; v1/64 + v0
        CMP     R1,#8
        BLT     |ADJUSTSTACKANDDONEXT2|

        MOV     R0,R7,ASR #6
        MOV     R2,R9,ASR #6 ; v1/64
        ADD     R0,R0,R4
        ADD     R2,R2,R6 ; v1/64 + v0
        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        MOV     R1,R2 ; screen y0

        LDMDB   R13,{R2-R4} ; load screen x1,rubbish,y1
        CMP     R3,#MaxThickPeruLineDist ; bug: R3 is corrupted
        MOV     R3,R4 ; screen y1

        STMFD   R13!,{R7-R12}
        BLT     |DRAWTHICKPERULINE|
        MOV     R4,#Peru
        BL      |DRAWLINE|
        LDMFD   R13!,{R7-R12}

        LDR     R14,|DRAWLINECOUNTER|                 ; -> Word: &00000000

        ADD     R7,R7,R10 ; v1*64 += v2
        ADD     R8,R8,R11
        ADD     R9,R9,R12

        SUBS    R14,R14,#1
        BPL     |DRAWPERULINELOOP|

        ADD     R13,R13,#&0C                    ; =12
        B       |DRAWNEXTPOLYGON|                     ; Ends

|DRAWTHICKPERULINE|
        MOV     R4,#Peru + TintHi                         ; ="^" (94)
        BL      |DRAWTHICK| ; In R0-R3 coords, R4 colour

        LDMFD   R13!,{R7-R12}
        LDR     R14,|DRAWLINECOUNTER|                 ; -> Word: &00000000

        ADD     R7,R7,R10
        ADD     R8,R8,R11
        ADD     R9,R9,R12

        SUBS    R14,R14,#1
        BPL     |DRAWPERULINELOOP|

        ADD     R13,R13,#&0C                    ; =12
        B       |DRAWNEXTPOLYGON|                     ; Ends

|THINWHITELINE8DASH|
        ; Draw a thin white line with 8 dashes
        LDR     R0,|LINECOORDS4|                  ; -> Word: MemLineCoords
        LDMIA   R0,{R7-R12}
        ; R7-R9   = v0 {x0,y0,z0}
        ; R10-R12 = v1 {x1,y1,z1}
        CMP     R8,R11
        BGT     |L0000EC38|

        SWAP    R7,R10,R4 ; swap v0,v1
        SWAP    R8,R11,R4
        SWAP    R9,R12,R4

        SUB     R10,R10,R7
        SUB     R11,R11,R8
        SUB     R12,R12,R9

        ADD     R7,R7,R10,ASR #4
        ADD     R8,R8,R11,ASR #4
        ADD     R9,R9,R12,ASR #4

        B       |L0000EC44|                     ; Ends
|L0000EC38|
        SUB     R10,R10,R7
        SUB     R11,R11,R8
        SUB     R12,R12,R9
|L0000EC44|
        MOV     R7,R7,LSL #3
        MOV     R8,R8,LSL #3
        MOV     R9,R9,LSL #3

        MOV     R14,#7
|L0000EC54|
        CMP     R8,#LineClipDist
        BLT     |DRAWNEXTPOLYGON|
        STR     R14,|DRAWLINECOUNTER|                 ; -> Word: &00000000
        MOV     R0,R7,ASR #3
        MOV     R1,R8,ASR #3
        MOV     R2,R9,ASR #3
        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        STMDB   R13,{R0,R2}
        MOV     R1,R8,ASR #3
        ADD     R1,R1,R11,ASR #4
        CMP     R1,#8
        BLT     |DRAWNEXTPOLYGON|
        MOV     R0,R7,ASR #3
        MOV     R2,R9,ASR #3
        ADD     R0,R0,R10,ASR #4
        ADD     R2,R2,R12,ASR #4
        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        MOV     R1,R2
        LDMDB   R13,{R2,R3}
        STMFD   R13!,{R7-R12}
        MOV     R4,#White                         ; ="" (255)
        BL      |DRAWLINE|
        LDMFD   R13!,{R7-R12}
        LDR     R14,|DRAWLINECOUNTER|                 ; -> Word: &00000000

        ADD     R7,R7,R10
        ADD     R8,R8,R11
        ADD     R9,R9,R12

        SUBS    R14,R14,#1
        BPL     |L0000EC54|

        B       |DRAWNEXTPOLYGON|                     ; Ends

|CAMPOSZ|
        DCD     |CAMERAPOSZ|
|LINECOORDS2B|
        DCD     &0002FDC0                       ; Word r/- (referenced)

|DRAWSPECIALTRIANGLE|
        ; r2 = special vertex no. (>= 248)
        CMP     R8,#3                           ; Function entry
        BEQ     |DRAWNEXTPOLYGON|
        CMP     R2,#Vertex16WhiteQuadsCheckZ                 ; ="" (253)
        CMPNE   R2,#Vertex8PeridotQuadsCheckZ                 ; ="" (252)
        BNE     |NOCHECKZ|

        LDR     R0,|CAMPOSZ|                  ; -> Word: &0001C7FC
        LDR     R0,[R0,#0] ; check camera height?
        CMN     R0,#MaxHeightDrawSpecialQuads    ; =&190
        BGT     |DRAWNEXTPOLYGON|
        ADD     R2,R2,#NoCheckZOffset

|NOCHECKZ|
        CMP     R2,#Vertex16ThinBlackZigzags    ; ="" (251)
        BEQ     |SPECIALBLACKZIGZAG| ; used for pier
        CMP     R2,#Vertex64ThickPeruLines              ; ="" (250)
        BEQ     |SPECIALPERULINES| ; used for railway track
        CMP     R2,#Vertex16DarkGreyQuads   ; ="" (249)
        BEQ     |SPECIALDARKGREYQUADS|
        CMP     R2,#Vertex32OrangePoints    ; ="" (248)
        BEQ     |SPECIALORANGEPOINTS| ; used for runway lights
        CMP     R2,#Vertex8PeridotQuads  ; ="" (254)
        BEQ     |SPECIALPERIDOTQUADS| ; used for runway threshold

        ; R2 = Vertex16WhiteQuads
        LDR     R0,|LINECOORDS4|                  ; -> Word: MemLineCoords
        LDMIA   R0!,{R7-R12}
        LDMIA   R0,{R4-R6}
        ; R7-R9   = v0 {x0,y0,z0}
        ; R10-R12 = v1 {x1,y1,z1}
        ; R4-R6   = v2 {x2,y2,z2}

        SUB     R4,R4,R7 ; v2 -= v0
        SUB     R5,R5,R8
        SUB     R6,R6,R9

        STMFD   R13!,{R4-R6} ; store v2'
        CMP     R8,R11
        BGT     |L0000ED88| ; y0 > y1

        SWAP    R7,R10,R3 ; swap v0,v1
        SWAP    R8,R11,R3
        SWAP    R9,R12,R3

        SUB     R10,R10,R7 ; v1 -= v0
        SUB     R11,R11,R8
        SUB     R12,R12,R9

        ADD     R7,R7,R10,ASR #5 ; v0 += v1/32
        ADD     R8,R8,R11,ASR #5
        ADD     R9,R9,R12,ASR #5

        B       |L0000ED94|                     ; Ends

|L0000ED88|
        SUB     R10,R10,R7 ; v1 -= v0
        SUB     R11,R11,R8
        SUB     R12,R12,R9
|L0000ED94|
        MOV     R7,R7,LSL #4 ; v0 *= 16
        MOV     R8,R8,LSL #4
        MOV     R9,R9,LSL #4
        MOV     R14,#&0F                        ; =15
|NEXTWHITEPRIMITIVE|
        CMP     R8,#LineClipDist
        BLT     |ADJUSTSTACKANDDONEXT|
        STR     R14,|DRAWLINECOUNTER|                 ; -> Word: &00000000
        MOV     R0,R7,ASR #4 ; v0/16
        MOV     R1,R8,ASR #4
        MOV     R2,R9,ASR #4
        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        LDR     R4,|LINECOORDS2B|                  ; -> Word: &0002FDC0
        STMIA   R4,{R0,R2} ; store screen x0,y0

        MOV     R0,R7,ASR #4
        MOV     R2,R9,ASR #4
        ADD     R0,R0,R10,ASR #5
        ADD     R2,R2,R12,ASR #5
        MOV     R1,R8,ASR #4
        ADD     R1,R1,R11,ASR #5 ; v0/16 + v1/32
        CMP     R1,#&1E                         ; =30
        BLLT    |CLIPWHITEPRIMITIVE|
        CMP     R8,#&02,18                      ; =&8000
        BLT     |DRAWWHITEQUAD| ; y0 too small

        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        MOV     R1,R2 ; screen y0
        LDR     R4,|LINECOORDS2B|                  ; -> Word: &0002FDC0
        LDMIA   R4,{R2,R3} ; load screen x1,y1

        STMFD   R13!,{R7-R12}
        MOV     R4,#White                         ; ="" (255)
        BL      |DRAWLINE|
        LDMFD   R13!,{R7-R12}

|FINISHEDWHITEPRIMITIVE|
        LDR     R14,|DRAWLINECOUNTER|                 ; -> Word: &00000000

        ADD     R7,R7,R10 ; v0*16 += v1
        ADD     R8,R8,R11
        ADD     R9,R9,R12

        SUBS    R14,R14,#1
        BPL     |NEXTWHITEPRIMITIVE|

|ADJUSTSTACKANDDONEXT|
        ADD     R13,R13,#&0C                    ; =12
        B       |DRAWNEXTPOLYGON|                     ; Ends

|CLIPWHITEPRIMITIVE|
        STMFD   R13!,{R7-R12,R14}               ; Function entry, (alters flags)

        MOV     R3,R7,ASR #4
        MOV     R4,R8,ASR #4
        MOV     R5,R9,ASR #4

        BL      |CLIPLINESTART|
        LDMFD   R13!,{R7-R12,R14}
        MOV     PC,R14                          ; Function exit, Ends

|DRAWWHITEQUAD|
        ; R0-R2 = v0/16 + v1/32
        ; R7-R9 = v0
        STMFD   R13!,{R0-R2}
        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        LDR     R4,|LINECOORDS2B|                  ; -> Word: &0002FDC0
        ADD     R4,R4,#8
        STMIA   R4,{R0,R2} ; store screen x1,y1
        LDMFD   R13!,{R0-R2}

        LDMFD   R13,{R3-R5} ; load v2'

        ADD     R0,R0,R3
        ADD     R1,R1,R4
        ADD     R2,R2,R5 ; v0/16 + v1/32 + v2'

        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        LDR     R4,|LINECOORDS2B|                  ; -> Word: &0002FDC0
        ADD     R4,R4,#&10                      ; =16
        STMIA   R4,{R0,R2} ; store screen x2,y2

        LDMFD   R13,{R3-R5} ; load v2'

        ADD     R0,R3,R7,ASR #4
        ADD     R1,R4,R8,ASR #4
        ADD     R2,R5,R9,ASR #4 ; v2' + v0/16
        BL      |PROJECT3D| ; In R0-R2, out R0,R2

        LDR     R4,|LINECOORDS2B|                  ; -> Word: &0002FDC0
        ADD     R4,R4,#&18                      ; =24
        STMIA   R4,{R0,R2} ; store screen x3,y3

        STMFD   R13!,{R7-R12}
        SUB     R0,R4,#&18                      ; =24
        MOV     R1,#White                         ; ="" (255)
        MOV     R2,#PolygonStyleNoOutline
        MOV     R12,#4 ; quadrilateral
        MOV     R3,#DrawPolygonMayDarken
        BL      |DRAWPOLYGON|
        LDMFD   R13!,{R7-R12}

        B       |FINISHEDWHITEPRIMITIVE|                     ; Ends

|CLIPPERIDOTPRIMITIVE|
        STMFD   R13!,{R7-R12,R14}               ; Function entry, (alters flags)

        MOV     R3,R7,ASR #3
        MOV     R4,R8,ASR #3
        MOV     R5,R9,ASR #3

        BL      |CLIPLINESTART|
        LDMFD   R13!,{R7-R12,R14}
        MOV     PC,R14                          ; Function exit, Ends

|SPECIALPERIDOTQUADS|
        LDR     R0,|LINECOORDS4|                  ; -> Word: MemLineCoords
        LDMIA   R0!,{R7-R12}
        LDMIA   R0,{R4-R6}
        ; R7-R9   = v0 {x0,y0,z0}
        ; R10-R12 = v1 {x1,y1,z1}
        ; R4-R6   = v2 {x2,y2,z2}

        CMP     R8,R5
        BGT     |L0000EF30| ; y0 > y2

        SWAP    R7,R4,R3 ; swap v0,v2
        SWAP    R8,R5,R3
        SWAP    R9,R6,R3

        SUB     R10,R10,R4 ; v1' = v1 - v2
        SUB     R11,R11,R5
        SUB     R12,R12,R6

        STMFD   R13!,{R10-R12} ; store v1'
        B       |L0000EF40|                     ; Ends

|L0000EF30|
        SUB     R10,R10,R7 ; v1' = v1 - v0
        SUB     R11,R11,R8
        SUB     R12,R12,R9
        STMFD   R13!,{R10-R12} ; store v1'
|L0000EF40|
        SUB     R10,R4,R7 ; v2' = v2 - v0
        SUB     R11,R5,R8
        SUB     R12,R6,R9

        MOV     R7,R7,LSL #3 ; v0 *= 8
        MOV     R8,R8,LSL #3
        MOV     R9,R9,LSL #3

        MOV     R14,#7
|PERIDOTPRIMITIVELOOP|
        CMP     R8,#&F0                         ; ="" (240)
        BLT     |SKIPPERIDOTPRIMITIVE|
        STR     R14,|DRAWLINECOUNTER|                 ; -> Word: &00000000

        MOV     R0,R7,ASR #3 ; v0/8
        MOV     R1,R8,ASR #3
        MOV     R2,R9,ASR #3

        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        LDR     R4,|LINECOORDS2B|                  ; -> Word: &0002FDC0
        STMIA   R4,{R0,R2}

        MOV     R0,R7,ASR #3 ; v0/8
        MOV     R2,R9,ASR #3
        ADD     R0,R0,R10 ; v0/8 + v2'
        ADD     R2,R2,R12
        MOV     R1,R8,ASR #3
        ADD     R1,R1,R11

        CMP     R1,#&1E                         ; =30
        BLLT    |CLIPPERIDOTPRIMITIVE|

        CMP     R8,#&01,18                      ; =&4000
        BLT     |DRAWPERIDOTQUAD|

        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        MOV     R1,R2
        LDR     R4,|LINECOORDS2B|                  ; -> Word: &0002FDC0
        LDMIA   R4,{R2,R3}

        STMFD   R13!,{R7-R12}
        MOV     R4,#Peridot
        BL      |DRAWLINE|
        LDMFD   R13!,{R7-R12}

|NEXTPERIDOTPRIMITIVE|
        LDR     R14,|DRAWLINECOUNTER|                 ; -> Word: &00000000
|SKIPPERIDOTPRIMITIVE|
        LDMFD   R13,{R4-R6}

        ADD     R7,R7,R4
        ADD     R8,R8,R5
        ADD     R9,R9,R6

        SUBS    R14,R14,#1
        BPL     |PERIDOTPRIMITIVELOOP|

        ADD     R13,R13,#&0C                    ; =12
        B       |DRAWNEXTPOLYGON|                     ; Ends

|DRAWPERIDOTQUAD|
        ; R0-R2 = v0/8 + v2'
        ; R7-R9 = v0
        STMFD   R13!,{R0-R2}
        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        LDR     R4,|LINECOORDS2B|                  ; -> Word: &0002FDC0
        ADD     R4,R4,#8
        STMIA   R4,{R0,R2}
        LDMFD   R13!,{R0-R2}

        LDMFD   R13,{R3-R5} ; get v1'

        ADD     R0,R0,R3,ASR #4 ; v0/8 + v2' + v1'/16
        ADD     R1,R1,R4,ASR #4
        ADD     R2,R2,R5,ASR #4

        BL      |PROJECT3D| ; In R0-R2, out R0,R2

        LDR     R4,|LINECOORDS2B|                  ; -> Word: &0002FDC0
        ADD     R4,R4,#&10                      ; =16
        STMIA   R4,{R0,R2}

        LDMFD   R13,{R3-R5} ; get v1'

        MOV     R3,R3,ASR #4
        MOV     R4,R4,ASR #4
        MOV     R5,R5,ASR #4

        ADD     R0,R3,R7,ASR #3 ; v0/8 + v1'/16
        ADD     R1,R4,R8,ASR #3
        ADD     R2,R5,R9,ASR #3

        BL      |PROJECT3D| ; In R0-R2, out R0,R2

        LDR     R4,|LINECOORDS2B|                  ; -> Word: &0002FDC0
        ADD     R4,R4,#&18                      ; =24
        STMIA   R4,{R0,R2}

        STMFD   R13!,{R7-R12}
        SUB     R0,R4,#&18                      ; =24
        MOV     R1,#Peridot
        MOV     R2,#PolygonStyleNoOutline
        MOV     R12,#4 ; quadrilateral
        MOV     R3,#DrawPolygonMayDarken
        BL      |DRAWPOLYGON|
        LDMFD   R13!,{R7-R12}

        B       |NEXTPERIDOTPRIMITIVE|                     ; Ends

|CLIPDARKGREYPRIMITIVE|
        STMFD   R13!,{R7-R12,R14}               ; Function entry, (alters flags)

        MOV     R3,R7,ASR #4
        MOV     R4,R8,ASR #4
        MOV     R5,R9,ASR #4

        BL      |CLIPLINESTART|
        LDMFD   R13!,{R7-R12,R14}

        MOV     PC,R14                          ; Function exit, Ends

|SPECIALDARKGREYQUADS|
        LDR     R0,|LINECOORDS4|                  ; -> Word: MemLineCoords
        LDMIA   R0!,{R7-R12}
        LDMIA   R0,{R4-R6}
        ; R7-R9   = v0 {x0,y0,z0}
        ; R10-R12 = v1 {x1,y1,z1}
        ; R4-R6   = v2 {x2,y2,z2}

        CMP     R8,R5
        BGT     |L0000F0DC|

        SWAP    R7,R4,R3 ; swap v0,v2
        SWAP    R8,R5,R3
        SWAP    R9,R6,R3

        SUB     R10,R10,R4 ; v1' = v1 - v2
        SUB     R11,R11,R5
        SUB     R12,R12,R6

        STMFD   R13!,{R10-R12} ; store v1'
        B       |L0000F0EC|                     ; Ends

|L0000F0DC|
        SUB     R10,R10,R7 ; v1' = v1 - v0
        SUB     R11,R11,R8
        SUB     R12,R12,R9
        STMFD   R13!,{R10-R12} ; store v1'
|L0000F0EC|
        SUB     R10,R4,R7 ; v2' = v2 - v0
        SUB     R11,R5,R8
        SUB     R12,R6,R9

        MOV     R7,R7,LSL #4 ; v0 *= 16
        MOV     R8,R8,LSL #4
        MOV     R9,R9,LSL #4

        MOV     R14,#&0F                        ; =15
|DARKGREYPRIMITIVELOOP|
        CMP     R8,#&19,26                      ; =&640
        BLT     |SKIPDARKGREYPRIMITIVE|
        STR     R14,|DRAWLINECOUNTER|                 ; -> Word: &00000000

        MOV     R0,R7,ASR #4 ; v0/16
        MOV     R1,R8,ASR #4
        MOV     R2,R9,ASR #4

        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        LDR     R4,|LINECOORDS2B|                  ; -> Word: &0002FDC0
        STMIA   R4,{R0,R2}

        MOV     R0,R7,ASR #4 ; v0/16
        MOV     R2,R9,ASR #4
        ADD     R0,R0,R10 ; v0/16 + v2'
        ADD     R2,R2,R12
        MOV     R1,R8,ASR #4
        ADD     R1,R1,R11

        CMP     R1,#&1E                         ; =30
        BLLT    |CLIPDARKGREYPRIMITIVE|
        CMP     R8,#&01,16                      ; =&10000
        BLT     |DRAWDARKGREYQUAD|
        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        MOV     R1,R2
        LDR     R4,|LINECOORDS2B|                  ; -> Word: &0002FDC0
        LDMIA   R4,{R2,R3}

        STMFD   R13!,{R7-R12}
        MOV     R4,#DarkerGrey
        BL      |DRAWTHICK| ; In R0-R3 coords, R4 colour
        LDMFD   R13!,{R7-R12}

|NEXTDARKGREYPRIMITIVE|
        LDR     R14,|DRAWLINECOUNTER|                 ; -> Word: &00000000
|SKIPDARKGREYPRIMITIVE|
        LDMFD   R13,{R4-R6}

        ADD     R7,R7,R4
        ADD     R8,R8,R5
        ADD     R9,R9,R6

        SUBS    R14,R14,#1
        BPL     |DARKGREYPRIMITIVELOOP|

        ADD     R13,R13,#&0C                    ; =12
        B       |DRAWNEXTPOLYGON|                     ; Ends

|DRAWDARKGREYQUAD|
        ; R0-R2 = v0/16 + v2'
        ; R7-R9 = v0
        STMFD   R13!,{R0-R2}
        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        LDR     R4,|LINECOORDS2B|                  ; -> Word: &0002FDC0
        ADD     R4,R4,#8
        STMIA   R4,{R0,R2}
        LDMFD   R13!,{R0-R2}

        LDMFD   R13,{R3-R5} ; get v1'

        ADD     R0,R0,R3,ASR #5 ; v0/16 + v2' + v1'/32
        ADD     R1,R1,R4,ASR #5
        ADD     R2,R2,R5,ASR #5

        BL      |PROJECT3D| ; In R0-R2, out R0,R2
        LDR     R4,|LINECOORDS2B|                  ; -> Word: &0002FDC0
        ADD     R4,R4,#&10                      ; =16
        STMIA   R4,{R0,R2}

        LDMFD   R13,{R3-R5} ; get v1'

        MOV     R3,R3,ASR #5
        MOV     R4,R4,ASR #5
        MOV     R5,R5,ASR #5

        ADD     R0,R3,R7,ASR #4 ; v0/16 + v1'/32
        ADD     R1,R4,R8,ASR #4
        ADD     R2,R5,R9,ASR #4

        BL      |PROJECT3D| ; In R0-R2, out R0,R2

        LDR     R4,|LINECOORDS2B|                  ; -> Word: &0002FDC0
        ADD     R4,R4,#&18                      ; =24
        STMIA   R4,{R0,R2}

        STMFD   R13!,{R7-R12}
        SUB     R0,R4,#&18                      ; =24
        MOV     R1,#DarkerGrey
        MOV     R2,#PolygonStyleNoOutline
        MOV     R12,#4 ; quadrilateral
        MOV     R3,#DrawPolygonMayDarken
        BL      |DRAWPOLYGON|
        LDMFD   R13!,{R7-R12}

        B       |NEXTDARKGREYPRIMITIVE|                     ; Ends

|L0000F220|
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-
        DCD     &00000000                       ;~ Word -/-

|L0000F230.End_Of_File|
          ;~

        END

